diff options
Diffstat (limited to 'sys/ia64')
94 files changed, 22323 insertions, 0 deletions
diff --git a/sys/ia64/conf/GENERIC b/sys/ia64/conf/GENERIC new file mode 100644 index 0000000..c5f9724 --- /dev/null +++ b/sys/ia64/conf/GENERIC @@ -0,0 +1,165 @@ +# +# GENERIC -- Generic kernel configuration file for FreeBSD/alpha +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/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 ../../i386/conf/NOTES file. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. Please note that this is the i386 NOTES, but it still contains +# valuable info for alpha too. +# +# For hardware specific information check HARDWARE.TXT +# +# $FreeBSD$ + +machine ia64 +cpu ITANIUM +ident GENERIC +maxusers 32 + +#To statically compile in device wiring instead of /boot/device.hints +#hints "GENERIC.hints" + +#makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols + +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +options FFS_ROOT #FFS usable as root device [keep this!] +options SOFTUPDATES #Enable FFS soft updates support +options MFS #Memory Filesystem +#options DEVFS #Device Filesystem +options MD_ROOT #MD is a potential root device +options NFS #Network Filesystem +options NFS_ROOT #NFS usable as root device +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options CD9660_ROOT #CD-ROM usable as root device +options PROCFS #Process filesystem +options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] +options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI +options UCONSOLE #Allow users to grab the console +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 P1003_1B #Posix P1003_1B real-time extentions +options _KPOSIX_PRIORITY_SCHEDULING + +# Standard busses +device isa +device pci +options COMPAT_OLDPCI # PCI compatability shims + +# Floppy drives +device fdc + +# 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 Controllers +device ahc # AHA2940 and onboard AIC7xxx devices +#device esp # 53C94 & friends, not CAM-ified +device isp # Qlogic family +#device ncr # NCR/Symbios Logic +device sym # NCR/Symbios Logic (newer chipsets + those of `ncr') + +# SCSI peripherals +device scbus # SCSI bus (required) +device da # Direct Access (disks) +device sa # Sequential Access (tape etc) +device cd # CD +device pass # Passthrough device (direct SCSI access) + +# RAID controllers +device amr # AMI MegaRAID +device mlx # Mylex DAC960 family + +# atkbdc0 controls both the keyboard and the PS/2 mouse +device atkbdc 1 +device atkbd +device psm + +#device vga + +# splash screen/screen saver +device splash + +# syscons is the default console driver, resembling an SCO console +#device sc 1 + +# real time clock +device mcclock + +# Serial (COM) ports +device sio + +# Parallel port +device ppc +device ppbus # Parallel port bus (required) +device lpt # Printer +device plip # TCP/IP over parallel +device ppi # Parallel port interface device +#device vpo # Requires scbus and da + +# PCI Ethernet NICs. +device de # DEC/Intel DC21x4x (``Tulip'') +device fxp # Intel EtherExpress PRO/100B (82557, 82558) +device wx # Intel Gigabit Ethernet Card (``Wiseman'') + +# PCI Ethernet NICs that use the common MII bus controller code. +device miibus # MII bus support +device dc # DEC/Intel 21143 and workalikes +device rl # RealTek 8129/8139 +device sf # Adaptec AIC-6915 (``Starfire'') +device sis # Silicon Integrated Systems SiS 900/SiS 7016 +device ste # Sundance ST201 (D-Link DFE-550TX) +device tl # Texas Instruments ThunderLAN +device tx # SMC 9432TX (83c170 ``EPIC'') +device vr # VIA Rhine, Rhine II +device wb # Winbond W89C840F +device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') + +# Pseudo devices - the number indicates how many units to allocated. +device random # Entropy device +device loop # Network loopback +device ether # Ethernet support +device sl # Kernel SLIP +device ppp 1 # Kernel PPP +device tun # Packet tunnel. +device pty # Pseudo-ttys (telnet etc) +device md # Memory "disks" +device gif 4 # IPv6 and IPv4 tunneling +device faith 1 # IPv6-to-IPv4 relaying/(translation) + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +device bpf #Berkeley packet filter + +# USB support +device uhci # UHCI PCI->USB interface +device ohci # OHCI PCI->USB interface +device usb # USB Bus (required) +device ugen # Generic +device uhid # "Human Interface Devices" +device ukbd # Keyboard +device ulpt # Printer +device umass # Disks/Mass storage - Requires scbus and da0 +device ums # Mouse +# USB Ethernet +device aue # ADMtek USB ethernet +device cue # CATC USB ethernet +device kue # Kawasaki LSI USB ethernet diff --git a/sys/ia64/conf/GENERIC.hints b/sys/ia64/conf/GENERIC.hints new file mode 100644 index 0000000..a007536 --- /dev/null +++ b/sys/ia64/conf/GENERIC.hints @@ -0,0 +1,26 @@ +# $FreeBSD$ +hint.fdc.0.at="isa" +hint.fdc.0.port="0x3F0" +hint.fdc.0.irq="6" +hint.fdc.0.drq="2" +hint.fd.0.at="fdc0" +hint.fd.0.drive="0" +hint.atkbdc.0.at="isa" +hint.atkbdc.0.port="0x060" +hint.atkbd.0.at="atkbdc" +hint.atkbd.0.irq="1" +hint.psm.0.at="atkbdc" +hint.psm.0.irq="12" +hint.vga.0.at="isa" +hint.sc.0.at="isa" +hint.mcclock.0.at="isa" +hint.mcclock.0.port="0x70" +hint.sio.0.at="isa" +hint.sio.0.port="0x3F8" +hint.sio.0.irq="4" +hint.sio.1.at="isa" +hint.sio.1.port="0x2F8" +hint.sio.1.irq="3" +hint.sio.1.flags="0x50" +hint.ppc.0.at="isa" +hint.ppc.0.irq="7" diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c new file mode 100644 index 0000000..66230b7 --- /dev/null +++ b/sys/ia64/ia64/autoconf.c @@ -0,0 +1,121 @@ +/*- + * 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$ + */ + +#include "opt_bootp.h" +#include "opt_ffs.h" +#include "opt_cd9660.h" +#include "opt_nfs.h" +#include "opt_nfsroot.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/disklabel.h> +#include <sys/diskslice.h> /* for BASE_SLICE, MAX_SLICES */ +#include <sys/reboot.h> +#include <sys/kernel.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <sys/bus.h> +#include <sys/devicestat.h> +#include <sys/cons.h> + +#include <machine/ipl.h> +#include <machine/md_var.h> +#include <machine/bootinfo.h> + +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_periph.h> +#include <cam/cam_xpt_sim.h> +#include <cam/cam_debug.h> + +static void configure __P((void *)); +SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL) + +#include "isa.h" +#if NISA > 0 +#include <isa/isavar.h> +device_t isa_bus_device = 0; +#endif + +extern int nfs_diskless_valid; + +dev_t rootdev = NODEV; +dev_t dumpdev = NODEV; + +/* + * Determine i/o configuration for a machine. + */ +static void +configure(void *dummy) +{ + device_add_child(root_bus, "nexus", 0); + + root_bus_configure(); + + /* + * Probe ISA devices after everything. + */ +#if NISA > 0 + if (isa_bus_device) + isa_probe_children(isa_bus_device); +#endif + + cninit_finish(); + + /* + * Now we're ready to handle (pending) interrupts. + * XXX this is slightly misplaced. + */ + spl0(); + + cold = 0; +} + +/* + * Do legacy root filesystem discovery. This isn't really + * needed on the Alpha, which has always used the loader. + */ +void +cpu_rootconf() +{ + int order = 0; +#if defined(NFS) && defined(NFS_ROOT) +#if !defined(BOOTP_NFSROOT) + if (nfs_diskless_valid) +#endif + rootdevnames[order++] = "nfs:"; +#endif + +#if defined(FFS) && defined(FFS_ROOT) + rootdevnames[order++] = "ufs:da0a"; +#endif +} +SYSINIT(cpu_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, cpu_rootconf, NULL) diff --git a/sys/ia64/ia64/busdma_machdep.c b/sys/ia64/ia64/busdma_machdep.c new file mode 100644 index 0000000..6696c58 --- /dev/null +++ b/sys/ia64/ia64/busdma_machdep.c @@ -0,0 +1,718 @@ +/* + * Copyright (c) 1997 Justin T. Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <machine/bus.h> +#include <machine/md_var.h> + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX_BPAGES 128 + +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; +}; + +struct bounce_page { + vm_offset_t vaddr; /* kva of bounce buffer */ + bus_addr_t busaddr; /* Physical address */ + vm_offset_t datavaddr; /* kva of client data */ + bus_size_t datacount; /* client data count */ + STAILQ_ENTRY(bounce_page) links; +}; + +int busdma_swi_pending; + +static STAILQ_HEAD(bp_list, bounce_page) bounce_page_list; +static int free_bpages; +static int reserved_bpages; +static int active_bpages; +static int total_bpages; +static bus_addr_t bounce_lowaddr = BUS_SPACE_MAXADDR; + +struct bus_dmamap { + struct bp_list bpages; + int pagesneeded; + int pagesreserved; + bus_dma_tag_t dmat; + void *buf; /* unmapped buffer pointer */ + bus_size_t buflen; /* unmapped buffer length */ + vm_offset_t busaddress; /* address in bus space */ + bus_dmamap_callback_t *callback; + void *callback_arg; + void *sgmaphandle; /* handle into sgmap */ + STAILQ_ENTRY(bus_dmamap) links; +}; + +static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist; +static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist; +static struct bus_dmamap nobounce_dmamap; + +static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages); +static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map); +static vm_offset_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_offset_t vaddr, bus_size_t size); +static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage); +static __inline int run_filter(bus_dma_tag_t dmat, bus_addr_t paddr); + +static __inline int +run_filter(bus_dma_tag_t dmat, bus_addr_t paddr) +{ + int retval; + + retval = 0; + do { + if (paddr > dmat->lowaddr + && paddr <= dmat->highaddr + && (dmat->filter == NULL + || (*dmat->filter)(dmat->filterarg, paddr) != 0)) + retval = 1; + + dmat = dmat->parent; + } while (retval == 0 && dmat != NULL); + return (retval); +} + +#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4 +/* + * Allocate a device specific dma_tag. + */ +int +bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, + bus_size_t boundary, bus_addr_t lowaddr, + bus_addr_t highaddr, bus_dma_filter_t *filter, + void *filterarg, bus_size_t maxsize, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat) +{ + bus_dma_tag_t newtag; + int error = 0; + + /* 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(lowaddr) + (PAGE_SIZE - 1); + newtag->highaddr = trunc_page(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; + + /* 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); + /* + * XXX Not really correct??? Probably need to honor boundary + * all the way up the inheritence chain. + */ + newtag->boundary = MAX(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) { + parent->ref_count++; + } + } + + if (newtag->lowaddr < ptoa(Maxmem) && (flags & BUS_DMA_ALLOCNOW) != 0) { + /* Must bounce */ + + if (lowaddr > bounce_lowaddr) { + /* + * Go through the pool and kill any pages + * that don't reside below lowaddr. + */ + panic("bus_dma_tag_create: page reallocation " + "not implemented"); + } + if (ptoa(total_bpages) < maxsize) { + int pages; + + pages = atop(maxsize) - total_bpages; + + /* Add pages to our bounce pool */ + if (alloc_bounce_pages(newtag, pages) < pages) + error = ENOMEM; + } + /* Performed initial allocation */ + newtag->flags |= BUS_DMA_MIN_ALLOC_COMP; + } + + if (error != 0) { + free(newtag, M_DEVBUF); + } else { + *dmat = newtag; + } + return (error); +} + +int +bus_dma_tag_destroy(bus_dma_tag_t dmat) +{ + if (dmat != NULL) { + + if (dmat->map_count != 0) + return (EBUSY); + + while (dmat != NULL) { + bus_dma_tag_t parent; + + parent = dmat->parent; + dmat->ref_count--; + if (dmat->ref_count == 0) { + free(dmat, M_DEVBUF); + } + dmat = parent; + } + } + return (0); +} + +/* + * Allocate a handle for mapping from kva/uva/physical + * address space into bus device space. + */ +int +bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) +{ + int error; + + error = 0; + + if (dmat->flags & BUS_DMA_ISA) { + bus_dmamap_t map; + map = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, + M_NOWAIT); + if (map == NULL) { + return (ENOMEM); + } else { + bzero(map, sizeof(*map)); +#if 0 + map->busaddress = + sgmap_alloc_region(chipset.sgmap, + dmat->maxsize, + dmat->boundary, + &map->sgmaphandle); +#endif + dmat->map_count++; + *mapp = map; + return (0); + } + } + + if (dmat->lowaddr < ptoa(Maxmem)) { + /* Must bounce */ + int maxpages; + + *mapp = (bus_dmamap_t)malloc(sizeof(**mapp), M_DEVBUF, + M_NOWAIT); + if (*mapp == NULL) { + return (ENOMEM); + } else { + /* Initialize the new map */ + bzero(*mapp, sizeof(**mapp)); + STAILQ_INIT(&((*mapp)->bpages)); + } + /* + * Attempt to add pages to our pool on a per-instance + * basis up to a sane limit. + */ + maxpages = MIN(MAX_BPAGES, Maxmem - atop(dmat->lowaddr)); + if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 + || (dmat->map_count > 0 + && total_bpages < maxpages)) { + int pages; + + if (dmat->lowaddr > bounce_lowaddr) { + /* + * Go through the pool and kill any pages + * that don't reside below lowaddr. + */ + panic("bus_dmamap_create: page reallocation " + "not implemented"); + } + pages = atop(dmat->maxsize); + pages = MIN(maxpages - total_bpages, pages); + error = alloc_bounce_pages(dmat, pages); + + if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) { + if (error == 0) + dmat->flags |= BUS_DMA_MIN_ALLOC_COMP; + } else { + error = 0; + } + } + } else { + *mapp = &nobounce_dmamap; + } + if (error == 0) + dmat->map_count++; + return (error); +} + +/* + * Destroy a handle for mapping from kva/uva/physical + * address space into bus device space. + */ +int +bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) +{ + if (dmat->flags & BUS_DMA_ISA) { +#if 0 + sgmap_free_region(chipset.sgmap, map->sgmaphandle); +#endif + } + + if (map != NULL) { + if (STAILQ_FIRST(&map->bpages) != NULL) + return (EBUSY); + free(map, M_DEVBUF); + } + 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) +{ + /* If we succeed, no mapping/bouncing will be required */ + *mapp = &nobounce_dmamap; + + if ((dmat->maxsize <= PAGE_SIZE) && dmat->lowaddr >= ptoa(Maxmem)) { + *vaddr = malloc(dmat->maxsize, M_DEVBUF, + (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK); + } 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, + (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK, + 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, + dmat->boundary); + } + if (*vaddr == NULL) + return (ENOMEM); + return (0); +} + +/* + * Free a piece of memory and it's allociated dmamap, that was allocated + * via bus_dmamem_alloc. + */ +void +bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +{ + /* + * dmamem does not need to be bounced, so the map should be + * NULL + */ + if (map != &nobounce_dmamap) + panic("bus_dmamem_free: Invalid map freed\n"); + free(vaddr, M_DEVBUF); +} + +#define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) + +/* + * Map the buffer buf into bus space using the dmamap map. + */ + +vm_offset_t alpha_XXX_dmamap_or = 1024UL*1024UL*1024UL; /*XXX */ + +int +bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, bus_dmamap_callback_t *callback, + void *callback_arg, int flags) +{ + vm_offset_t vaddr; + vm_offset_t paddr; +#ifdef __GNUC__ + bus_dma_segment_t dm_segments[dmat->nsegments]; +#else + bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; +#endif + bus_dma_segment_t *sg; + int seg; + int error; + vm_offset_t nextpaddr; + + error = 0; + + if (dmat->flags & BUS_DMA_ISA) { + /* + * For ISA dma, we use the chipset's scatter-gather + * map to map the tranfer into the ISA reachable range + * of the bus address space. + */ + vaddr = trunc_page((vm_offset_t) buf); + dm_segments[0].ds_addr = + map->busaddress + (vm_offset_t) buf - vaddr; + dm_segments[0].ds_len = buflen; + buflen = round_page((vm_offset_t) buf + buflen) - vaddr; +#if 0 + sgmap_load_region(chipset.sgmap, + map->busaddress, + vaddr, + buflen); +#endif + map->buflen = buflen; + (*callback)(callback_arg, dm_segments, 1, error); + + return (0); + } + + /* + * If we are being called during a callback, pagesneeded will + * be non-zero, so we can avoid doing the work twice. + */ + if (dmat->lowaddr < ptoa(Maxmem) && map->pagesneeded == 0) { + vm_offset_t vendaddr; + + /* + * Count the number of bounce pages + * needed in order to complete this transfer + */ + vaddr = trunc_page(buf); + vendaddr = (vm_offset_t)buf + buflen; + + while (vaddr < vendaddr) { + paddr = pmap_kextract(vaddr); + if (run_filter(dmat, paddr) != 0) { + + map->pagesneeded++; + } + vaddr += PAGE_SIZE; + } + } + + /* Reserve Necessary Bounce Pages */ + if (map->pagesneeded != 0) { + int s; + + s = splhigh(); + if (reserve_bounce_pages(dmat, map) != 0) { + + /* Queue us for resources */ + map->dmat = dmat; + map->buf = buf; + map->buflen = buflen; + map->callback = callback; + map->callback_arg = callback_arg; + + STAILQ_INSERT_TAIL(&bounce_map_waitinglist, map, links); + splx(s); + + return (EINPROGRESS); + } + splx(s); + } + + vaddr = (vm_offset_t)buf; + sg = &dm_segments[0]; + seg = 1; + sg->ds_len = 0; + + nextpaddr = 0; + + do { + bus_size_t size; + + paddr = pmap_kextract(vaddr); + size = PAGE_SIZE - (paddr & PAGE_MASK); + if (size > buflen) + size = buflen; + + if (map->pagesneeded != 0 && run_filter(dmat, paddr)) { + paddr = add_bounce_page(dmat, map, vaddr, size); + } + + if (sg->ds_len == 0) { + sg->ds_addr = paddr + alpha_XXX_dmamap_or; + sg->ds_len = size; + } else if (paddr == nextpaddr) { + sg->ds_len += size; + } else { + /* Go to the next segment */ + sg++; + seg++; + if (seg > dmat->nsegments) + break; + sg->ds_addr = paddr + alpha_XXX_dmamap_or; + sg->ds_len = size; + } + vaddr += size; + nextpaddr = paddr + size; + buflen -= size; + + } while (buflen > 0); + + if (buflen != 0) { + printf("bus_dmamap_load: Too many segs! buf_len = 0x%lx\n", + buflen); + error = EFBIG; + } + + (*callback)(callback_arg, dm_segments, seg, error); + + return (0); +} + +/* + * Release the mapping held by map. + */ +void +_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) +{ + struct bounce_page *bpage; + + if (dmat->flags & BUS_DMA_ISA) { +#if 0 + sgmap_unload_region(chipset.sgmap, + map->busaddress, + map->buflen); +#endif + return; + } + + while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { + STAILQ_REMOVE_HEAD(&map->bpages, links); + free_bounce_page(dmat, bpage); + } +} + +void +_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) +{ + struct bounce_page *bpage; + + if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) { + + /* + * Handle data bouncing. We might also + * want to add support for invalidating + * the caches on broken hardware + */ + switch (op) { + case BUS_DMASYNC_PREWRITE: + while (bpage != NULL) { + bcopy((void *)bpage->datavaddr, + (void *)bpage->vaddr, + bpage->datacount); + bpage = STAILQ_NEXT(bpage, links); + } + break; + + case BUS_DMASYNC_POSTREAD: + while (bpage != NULL) { + bcopy((void *)bpage->vaddr, + (void *)bpage->datavaddr, + bpage->datacount); + bpage = STAILQ_NEXT(bpage, links); + } + break; + case BUS_DMASYNC_PREREAD: + case BUS_DMASYNC_POSTWRITE: + /* No-ops */ + break; + } + } +} + +static int +alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages) +{ + int count; + + count = 0; + if (total_bpages == 0) { + STAILQ_INIT(&bounce_page_list); + STAILQ_INIT(&bounce_map_waitinglist); + STAILQ_INIT(&bounce_map_callbacklist); + } + + while (numpages > 0) { + struct bounce_page *bpage; + int s; + + bpage = (struct bounce_page *)malloc(sizeof(*bpage), M_DEVBUF, + M_NOWAIT); + + if (bpage == NULL) + break; + bzero(bpage, sizeof(*bpage)); + bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF, + M_NOWAIT, 0ul, + dmat->lowaddr, + PAGE_SIZE, + 0); + if (bpage->vaddr == NULL) { + free(bpage, M_DEVBUF); + break; + } + bpage->busaddr = pmap_kextract(bpage->vaddr); + s = splhigh(); + STAILQ_INSERT_TAIL(&bounce_page_list, bpage, links); + total_bpages++; + free_bpages++; + splx(s); + count++; + numpages--; + } + return (count); +} + +static int +reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map) +{ + int pages; + + pages = MIN(free_bpages, map->pagesneeded - map->pagesreserved); + free_bpages -= pages; + reserved_bpages += pages; + map->pagesreserved += pages; + pages = map->pagesneeded - map->pagesreserved; + + return (pages); +} + +static vm_offset_t +add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr, + bus_size_t size) +{ + int s; + struct bounce_page *bpage; + + if (map->pagesneeded == 0) + panic("add_bounce_page: map doesn't need any pages"); + map->pagesneeded--; + + if (map->pagesreserved == 0) + panic("add_bounce_page: map doesn't need any pages"); + map->pagesreserved--; + + s = splhigh(); + bpage = STAILQ_FIRST(&bounce_page_list); + if (bpage == NULL) + panic("add_bounce_page: free page list is empty"); + + STAILQ_REMOVE_HEAD(&bounce_page_list, links); + reserved_bpages--; + active_bpages++; + splx(s); + + bpage->datavaddr = vaddr; + bpage->datacount = size; + STAILQ_INSERT_TAIL(&(map->bpages), bpage, links); + return (bpage->busaddr); +} + +static void +free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage) +{ + int s; + struct bus_dmamap *map; + + bpage->datavaddr = 0; + bpage->datacount = 0; + + s = splhigh(); + STAILQ_INSERT_HEAD(&bounce_page_list, bpage, links); + free_bpages++; + active_bpages--; + if ((map = STAILQ_FIRST(&bounce_map_waitinglist)) != NULL) { + if (reserve_bounce_pages(map->dmat, map) == 0) { + STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links); + STAILQ_INSERT_TAIL(&bounce_map_callbacklist, + map, links); + busdma_swi_pending = 1; + setsoftvm(); + } + } + splx(s); +} + +void +busdma_swi(void) +{ + int s; + struct bus_dmamap *map; + + s = splhigh(); + while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) { + STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links); + splx(s); + bus_dmamap_load(map->dmat, map, map->buf, map->buflen, + map->callback, map->callback_arg, /*flags*/0); + s = splhigh(); + } + splx(s); +} diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c new file mode 100644 index 0000000..06a7f0c --- /dev/null +++ b/sys/ia64/ia64/clock.c @@ -0,0 +1,511 @@ +/* $FreeBSD$ */ +/* $NetBSD: clock.c,v 1.20 1998/01/31 10:32:47 ross Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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: Utah Hdr: clock.c 1.18 91/01/21 + * + * @(#)clock.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/queue.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/timetc.h> + +#include <machine/clock.h> +#include <machine/clockvar.h> +#include <isa/isareg.h> +#include <ia64/ia64/timerreg.h> + +#define SECMIN ((unsigned)60) /* seconds per minute */ +#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */ +#define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */ +#define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */ + +/* + * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we + * can use a simple formula for leap years. + */ +#define LEAPYEAR(y) (((y) % 4) == 0) + +device_t clockdev; +int clockinitted; +int tickfix; +int tickfixinterval; +int adjkerntz; /* local offset from GMT in seconds */ +int disable_rtc_set; /* disable resettodr() if != 0 */ +int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */ +static int beeping = 0; + +extern int cycles_per_sec; + +static timecounter_get_t ia64_get_timecount; + +static struct timecounter ia64_timecounter = { + ia64_get_timecount, /* get_timecount */ + 0, /* no poll_pps */ + ~0u, /* counter_mask */ + 0, /* frequency */ + "alpha" /* name */ +}; + +SYSCTL_OPAQUE(_debug, OID_AUTO, ia64_timecounter, CTLFLAG_RD, + &ia64_timecounter, sizeof(ia64_timecounter), "S,timecounter", ""); + +/* Values for timerX_state: */ +#define RELEASED 0 +#define RELEASE_PENDING 1 +#define ACQUIRED 2 +#define ACQUIRE_PENDING 3 + +/* static u_char timer0_state; */ +static u_char timer2_state; + +/* + * Algorithm for missed clock ticks from Linux/alpha. + */ + +/* + * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting + * by 48 gives us 16 bits for HZ while keeping the accuracy good even + * for large CPU clock rates. + */ +#define FIX_SHIFT 48 + +static u_int64_t scaled_ticks_per_cycle; +static u_int32_t max_cycles_per_tick; +static u_int32_t last_time; + +static void handleclock(void* arg); +static u_int32_t calibrate_clocks(u_int32_t firmware_freq); + +void +clockattach(device_t dev) +{ + + /* + * Just bookkeeping. + */ + if (clockdev) + panic("clockattach: multiple clocks"); + clockdev = dev; + cycles_per_sec = calibrate_clocks(cycles_per_sec); +#ifdef EVCNT_COUNTERS + evcnt_attach(dev, "intr", &clock_intr_evcnt); +#endif +} + +/* + * Machine-dependent clock routines. + * + * Startrtclock restarts the real-time clock, which provides + * hardclock interrupts to kern_clock.c. + * + * Inittodr initializes the time of day hardware which provides + * date functions. Its primary function is to use some file + * system information in case the hardare clock lost state. + * + * Resettodr restores the time of day hardware after a time change. + */ + +/* + * Start the real-time and statistics clocks. Leave stathz 0 since there + * are no other timers available. + */ +void +cpu_initclocks() +{ + u_int32_t freq; + + if (clockdev == NULL) + panic("cpu_initclocks: no clock attached"); + + tick = 1000000 / hz; /* number of microseconds between interrupts */ + tickfix = 1000000 - (hz * tick); + if (tickfix) { + int ftp; + + ftp = min(ffs(tickfix), ffs(hz)); + tickfix >>= (ftp - 1); + tickfixinterval = hz >> (ftp - 1); + } + + /* + * Establish the clock interrupt; it's a special case. + * + * We establish the clock interrupt this late because if + * we do it at clock attach time, we may have never been at + * spl0() since taking over the system. Some versions of + * PALcode save a clock interrupt, which would get delivered + * when we spl0() in autoconf.c. If established the clock + * interrupt handler earlier, that interrupt would go to + * hardclock, which would then fall over because p->p_stats + * isn't set at that time. + */ + freq = cycles_per_sec; + last_time = ia64_read_itc(); + scaled_ticks_per_cycle = ((u_int64_t)hz << FIX_SHIFT) / freq; + max_cycles_per_tick = 2*freq / hz; + + ia64_timecounter.tc_frequency = freq; + tc_init(&ia64_timecounter); + + stathz = 128; + + /* + * Get the clock started. + */ + CLOCK_INIT(clockdev); +} + +static u_int32_t +calibrate_clocks(u_int32_t firmware_freq) +{ + u_int32_t start_pcc, stop_pcc; + int sec, start_sec; + + if (bootverbose) + printf("Calibrating clock(s) ... "); + + /* Read the mc146818A seconds counter. */ + if (CLOCK_GETSECS(clockdev, &sec)) + goto fail; + + /* Wait for the mC146818A seconds counter to change. */ + start_sec = sec; + for (;;) { + if (CLOCK_GETSECS(clockdev, &sec)) + goto fail; + if (sec != start_sec) + break; + } + + /* Start keeping track of the PCC. */ + start_pcc = ia64_read_itc(); + + /* + * Wait for the mc146818A seconds counter to change. + */ + start_sec = sec; + for (;;) { + if (CLOCK_GETSECS(clockdev, &sec)) + goto fail; + if (sec != start_sec) + break; + } + + /* + * Read the PCC again to work out frequency. + */ + stop_pcc = ia64_read_itc(); + + if (bootverbose) { + printf("PCC clock: %u Hz (firmware %u Hz)\n", + stop_pcc - start_pcc, firmware_freq); + } + return (stop_pcc - start_pcc); + +fail: + if (bootverbose) + printf("failed, using firmware default of %u Hz\n", + firmware_freq); + return (firmware_freq); +} + +static void +handleclock(void* arg) +{ + u_int32_t now = ia64_read_itc(); + u_int32_t delta = now - last_time; + last_time = now; + + if (delta > max_cycles_per_tick) { + int i, missed_ticks; + missed_ticks = (delta * scaled_ticks_per_cycle) >> FIX_SHIFT; + for (i = 0; i < missed_ticks; i++) + hardclock(arg); + } + hardclock(arg); + setdelayed(); +} + +/* + * We assume newhz is either stathz or profhz, and that neither will + * change after being set up above. Could recalculate intervals here + * but that would be a drag. + */ +void +setstatclockrate(newhz) + int newhz; +{ + + /* nothing we can do */ +} + +/* + * This code is defunct after 2099. + * Will Unix still be here then?? + */ +static short dayyr[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +/* + * Initialze the time of day register, based on the time base which is, e.g. + * from a filesystem. Base provides the time to within six months, + * and the time of year clock (if any) provides the rest. + */ +void +inittodr(base) + time_t base; +{ + register int days, yr; + struct clocktime ct; + time_t deltat; + int badbase; + int s; + struct timespec ts; + + if (base < 5*SECYR) { + printf("WARNING: preposterous time in file system"); + /* read the system clock anyway */ + base = 6*SECYR + 186*SECDAY + SECDAY/2; + badbase = 1; + } else + badbase = 0; + + CLOCK_GET(clockdev, base, &ct); + clockinitted = 1; + + /* simple sanity checks */ + if (ct.year < 70 || ct.mon < 1 || ct.mon > 12 || ct.day < 1 || + ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) { + /* + * Believe the time in the file system for lack of + * anything better, resetting the TODR. + */ + s = splclock(); + ts.tv_sec = base; + ts.tv_nsec = 0; + tc_setclock(&ts); + splx(s); + if (!badbase) { + printf("WARNING: preposterous clock chip time\n"); + resettodr(); + } + goto bad; + } + days = 0; + for (yr = 70; yr < ct.year; yr++) + days += LEAPYEAR(yr) ? 366 : 365; + days += dayyr[ct.mon - 1] + ct.day - 1; + if (LEAPYEAR(yr) && ct.mon > 2) + days++; + /* now have days since Jan 1, 1970; the rest is easy... */ + s = splclock(); + ts.tv_sec = + days * SECDAY + ct.hour * SECHOUR + ct.min * SECMIN + ct.sec; + if (wall_cmos_clock) + ts.tv_sec += adjkerntz; + ts.tv_nsec = 0; + tc_setclock(&ts); + splx(s); + + if (!badbase) { + /* + * See if we gained/lost two or more days; + * if so, assume something is amiss. + */ + deltat = ts.tv_sec - base; + if (deltat < 0) + deltat = -deltat; + if (deltat < 2 * SECDAY) + return; + printf("WARNING: clock %s %d days", + ts.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + } +bad: + printf(" -- CHECK AND RESET THE DATE!\n"); +} + +/* + * Reset the TODR based on the time value; used when the TODR + * has a preposterous value and also when the time is reset + * by the stime system call. Also called when the TODR goes past + * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) + * to wrap the TODR around. + */ +void +resettodr() +{ + register int t, t2, s; + struct clocktime ct; + unsigned long tm; + + if (disable_rtc_set) + return; + + s = splclock(); + tm = time_second; + splx(s); + + if (!clockinitted) + return; + + /* Calculate local time to put in RTC */ + tm -= (wall_cmos_clock ? adjkerntz : 0); + + /* compute the day of week. */ + t2 = tm / SECDAY; + ct.dow = (t2 + 4) % 7; /* 1/1/1970 was thursday */ + + /* compute the year */ + ct.year = 69; + t = t2; /* XXX ? */ + while (t2 >= 0) { /* whittle off years */ + t = t2; + ct.year++; + t2 -= LEAPYEAR(ct.year) ? 366 : 365; + } + + /* t = month + day; separate */ + t2 = LEAPYEAR(ct.year); + for (ct.mon = 1; ct.mon < 12; ct.mon++) + if (t < dayyr[ct.mon] + (t2 && ct.mon > 1)) + break; + + ct.day = t - dayyr[ct.mon - 1] + 1; + if (t2 && ct.mon > 2) + ct.day--; + + /* the rest is easy */ + t = tm % SECDAY; + ct.hour = t / SECHOUR; + t %= 3600; + ct.min = t / SECMIN; + ct.sec = t % SECMIN; + + CLOCK_SET(clockdev, &ct); +} + +static unsigned +ia64_get_timecount(struct timecounter* tc) +{ + return ia64_read_itc(); +} + +int +acquire_timer2(int mode) +{ + + if (timer2_state != RELEASED) + return (-1); + timer2_state = ACQUIRED; + + /* + * This access to the timer registers is as atomic as possible + * because it is a single instruction. We could do better if we + * knew the rate. Use of splclock() limits glitches to 10-100us, + * and this is probably good enough for timer2, so we aren't as + * careful with it as with timer0. + */ + outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f)); + + return (0); +} + +int +release_timer2() +{ + + if (timer2_state != ACQUIRED) + return (-1); + timer2_state = RELEASED; + outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT); + return (0); +} + +static void +sysbeepstop(void *chan) +{ + outb(IO_PPI, inb(IO_PPI)&0xFC); /* disable counter2 output to speaker */ + release_timer2(); + beeping = 0; +} + +/* + * Frequency of all three count-down timers; (TIMER_FREQ/freq) is the + * appropriate count to generate a frequency of freq hz. + */ +#ifndef TIMER_FREQ +#define TIMER_FREQ 1193182 +#endif +#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x)) + +int +sysbeep(int pitch, int period) +{ + int x = splhigh(); + + if (acquire_timer2(TIMER_SQWAVE|TIMER_16BIT)) + if (!beeping) { + /* Something else owns it. */ + splx(x); + return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */ + } + + if (pitch) pitch = TIMER_DIV(pitch); + + outb(TIMER_CNTR2, pitch); + outb(TIMER_CNTR2, (pitch>>8)); + if (!beeping) { + /* enable counter2 output to speaker */ + if (pitch) outb(IO_PPI, inb(IO_PPI) | 3); + beeping = period; + timeout(sysbeepstop, (void *)NULL, period); + } + splx(x); + return (0); +} + diff --git a/sys/ia64/ia64/clock_if.m b/sys/ia64/ia64/clock_if.m new file mode 100644 index 0000000..9665135 --- /dev/null +++ b/sys/ia64/ia64/clock_if.m @@ -0,0 +1,52 @@ +# +# 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$ +# + +#include <sys/bus.h> +#include <machine/clockvar.h> + +INTERFACE clock; + +METHOD void init { + device_t dev; +}; + +METHOD void get { + device_t dev; + time_t base; + struct clocktime *ct; +}; + +METHOD void set { + device_t dev; + struct clocktime *ct; +}; + +METHOD int getsecs { + device_t dev; + int *secp; +}; diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c new file mode 100644 index 0000000..62302d9 --- /dev/null +++ b/sys/ia64/ia64/elf_machdep.c @@ -0,0 +1,76 @@ +/*- + * 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/malloc.h> +#include <sys/proc.h> +#include <sys/namei.h> +#include <sys/fcntl.h> +#include <sys/vnode.h> +#include <sys/linker.h> +#include <machine/elf.h> + +/* Process one elf relocation with addend. */ +int +elf_reloc(linker_file_t lf, const void *data, int type, const char *sym) +{ + Elf_Addr relocbase = (Elf_Addr) lf->address; + Elf_Addr *where; + Elf_Addr addr; + Elf_Addr addend; + Elf_Word rtype; + const Elf_Rel *rel; + const Elf_Rela *rela; + + switch (type) { + case ELF_RELOC_REL: + rel = (const Elf_Rel *)data; + where = (Elf_Addr *) (relocbase + rel->r_offset); + addend = *where; + rtype = ELF_R_TYPE(rel->r_info); + break; + case ELF_RELOC_RELA: + rela = (const Elf_Rela *)data; + where = (Elf_Addr *) (relocbase + rela->r_offset); + addend = rela->r_addend; + rtype = ELF_R_TYPE(rela->r_info); + break; + default: + panic("elf_reloc: unknown relocation mode %d\n", type); + } + + switch (rtype) { + + default: + printf("kldload: unexpected relocation type %d\n", + (int) rtype); + return -1; + } + return(0); +} diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S new file mode 100644 index 0000000..0f06ef0 --- /dev/null +++ b/sys/ia64/ia64/exception.S @@ -0,0 +1,949 @@ +/*- + * 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 <machine/asm.h> +#include <machine/pmap.h> +#include <assym.s> + +/* + * ar.k7 = curproc + * ar.k6 = ksp + */ + +/* + * Call exception_save_regs to preserve the interrupted state in a + * trapframe and call trap() with the value of _n_ as an argument. We + * arrange for trap() to return to exception_return which will restore + * the interrupted state before executing an rfi to resume it. + */ +#define TRAP(_n_) \ + mov r16=b0; \ + br.call.sptk.few b0=exception_save_regs; \ + alloc r16=ar.pfs,0,0,2,0; \ + movl r17=exception_return; \ + mov out0=_n_; \ + mov out1=sp;; \ + mov rp=r17; \ + br.call.sptk.few b6=trap + +/* + * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 + * bundles per vector and 48 slots with 16 bundles per vector. + */ + + .section .text.ivt,"ax" + + .align 32768 + .global ia64_vector_table +ia64_vector_table: + +/* 0x0000: VHPT Translation vector */ + + TRAP(0) + .align 1024 + +/* 0x0400: Instruction TLB vector */ + + mov r16=cr.ifa + mov r17=pr + ;; + thash r18=r16 + ttag r19=r16 + ;; + add r20=24,r18 // collision chain + ;; + ld8 r20=[r20] // first entry + ;; + rsm psr.dt // turn off data translations + ;; + srlz.d // serialize + ;; +1: cmp.eq p1,p2=r0,r20 // done? +(p1) br.cond.spnt.few 9f // bail if done + ;; + add r21=16,r20 // tag location + ;; + ld8 r21=[r21] // read tag + ;; + cmp.eq p1,p2=r21,r19 // compare tags +(p2) br.cond.sptk.few 2f // if not, read next in chain + ;; + ld8 r21=[r20],8 // read pte + ;; + ld8 r22=[r20] // read rest of pte + ;; + dep r18=0,r18,61,3 // convert vhpt ptr to physical + ;; + add r20=16,r18 // address of tag + ;; + ld8.acq r23=[r20] // read old tag + movl r24=(1<<63) // ti bit + ;; + or r23=r23,r24 // set ti bit + ;; + st8.rel [r20]=r23 // store old tag + ti + ;; + mf // make sure everyone sees + ;; + st8 [r18]=r21,8 // store pte + ;; + st8 [r18]=r22,8 + ;; + st8.rel [r18]=r19 // store new tag + ;; + mov pr=r17,0x1ffff // restore predicates + ;; + rfi // walker will retry the access + +2: add r20=24,r20 // next in chain + ;; + ld8 r20=[r20] // read chain + br.cond.sptk.few 1b // loop + +9: mov pr=r17,0x1ffff // restore predicates + TRAP(1) // die horribly + + .align 1024 + +/* 0x0800: Data TLB vector */ + + mov r16=cr.ifa + mov r17=pr + ;; + thash r18=r16 + ttag r19=r16 + ;; + add r20=24,r18 // collision chain + ;; + ld8 r20=[r20] // first entry + ;; + rsm psr.dt // turn off data translations + ;; + srlz.d // serialize + ;; +1: cmp.eq p1,p2=r0,r20 // done? +(p1) br.cond.spnt.few 9f // bail if done + ;; + add r21=16,r20 // tag location + ;; + ld8 r21=[r21] // read tag + ;; + cmp.eq p1,p2=r21,r19 // compare tags +(p2) br.cond.sptk.few 2f // if not, read next in chain + ;; + ld8 r21=[r20],8 // read pte + ;; + ld8 r22=[r20] // read rest of pte + ;; + dep r18=0,r18,61,3 // convert vhpt ptr to physical + ;; + add r20=16,r18 // address of tag + ;; + ld8.acq r23=[r20] // read old tag + movl r24=(1<<63) // ti bit + ;; + or r23=r23,r24 // set ti bit + ;; + st8.rel [r20]=r23 // store old tag + ti + ;; + mf // make sure everyone sees + ;; + st8 [r18]=r21,8 // store pte + ;; + st8 [r18]=r22,8 + ;; + st8.rel [r18]=r19 // store new tag + ;; + mov pr=r17,0x1ffff // restore predicates + ;; + rfi // walker will retry the access + +2: add r20=24,r20 // next in chain + ;; + ld8 r20=[r20] // read chain + br.cond.sptk.few 1b // loop + +9: mov pr=r17,0x1ffff // restore predicates + TRAP(2) // die horribly + + .align 1024 + +/* 0x0c00: Alternate Instruction TLB vector */ + + mov r16=cr.ifa // where did it happen + ;; + mov r18=pr // save predicates + ;; + extr.u r17=r16,61,3 // get region number + ;; + cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 + ;; +(p1) movl r17=PTE_P+PTE_MA_WC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX +(p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX + ;; + dep r16=0,r16,50,14 // clear bits above PPN + ;; + dep r16=r17,r17,0,12 // put pte bits in 0..11 + ;; + itc.i r16 + mov pr=r18,0x1ffff // restore predicates + ;; + rfi + + .align 1024 + +/* 0x1000: Alternate Data TLB vector */ + + mov r16=cr.ifa // where did it happen + mov r18=pr // save predicates + ;; + extr.u r17=r16,61,3 // get region number + ;; + cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 + ;; +(p1) movl r17=PTE_P+PTE_MA_WC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW +(p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW + ;; + dep r16=0,r16,50,14 // clear bits above PPN + ;; + dep r16=r17,r17,0,12 // put pte bits in 0..11 + ;; + itc.d r16 + mov pr=r18,0x1ffff // restore predicates + ;; + rfi + + .align 1024 + +/* 0x1400: Data Nested TLB vector */ + + TRAP(5) + .align 1024 + +/* 0x1800: Instruction Key Miss vector */ + + TRAP(6) + .align 1024 + +/* 0x1c00: Data Key Miss vector */ + + TRAP(7) + .align 1024 + +/* 0x2000: Dirty-Bit vector */ + + TRAP(8) + .align 1024 + +/* 0x2400: Instruction Access-Bit vector */ + + TRAP(9) + .align 1024 + +/* 0x2800: Data Access-Bit vector */ + + TRAP(10) + .align 1024 + +/* 0x2c00: Break Instruction vector */ + + TRAP(11) + .align 1024 + +/* 0x3000: External Interrupt vector */ + + TRAP(12) + .align 1024 + +/* 0x3400: Reserved */ + + TRAP(13) + .align 1024 + +/* 0x3800: Reserved */ + + TRAP(14) + .align 1024 + +/* 0x3c00: Reserved */ + + TRAP(15) + .align 1024 + +/* 0x4000: Reserved */ + + TRAP(16) + .align 1024 + +/* 0x4400: Reserved */ + + TRAP(17) + .align 1024 + +/* 0x4800: Reserved */ + + TRAP(18) + .align 1024 + +/* 0x4c00: Reserved */ + + TRAP(19) + .align 1024 + +/* 0x5000: Page Not Present vector */ + + TRAP(20) + .align 256 + +/* 0x5100: Key Permission vector */ + + TRAP(21) + .align 256 + +/* 0x5200: Instruction Access Rights vector */ + + TRAP(22) + .align 256 + +/* 0x5300: Data Access Rights vector */ + + TRAP(23) + .align 256 + +/* 0x5400: General Exception vector */ + + TRAP(24) + .align 256 + +/* 0x5500: Disabled FP-Register vector */ + + TRAP(25) + .align 256 + +/* 0x5600: NaT Consumption vector */ + + TRAP(26) + .align 256 + +/* 0x5700: Speculation vector */ + + TRAP(27) + .align 256 + +/* 0x5800: Reserved */ + + TRAP(28) + .align 256 + +/* 0x5900: Debug vector */ + + TRAP(29) + .align 256 + +/* 0x5a00: Unaligned Reference vector */ + + TRAP(30) + .align 256 + +/* 0x5b00: Unsupported Data Reference vector */ + + TRAP(31) + .align 256 + +/* 0x5c00: Floating-point Fault vector */ + + TRAP(32) + .align 256 + +/* 0x5d00: Floating-point Trap vector */ + + TRAP(33) + .align 256 + +/* 0x5e00: Lower-Privilege Transfer Trap vector */ + + TRAP(34) + .align 256 + +/* 0x5f00: Taken Branch Trap vector */ + + TRAP(35) + .align 256 + +/* 0x6000: Single Step Trap vector */ + + TRAP(36) + .align 256 + +/* 0x6100: Reserved */ + + TRAP(37) + .align 256 + +/* 0x6200: Reserved */ + + TRAP(38) + .align 256 + +/* 0x6300: Reserved */ + + TRAP(39) + .align 256 + +/* 0x6400: Reserved */ + + TRAP(40) + .align 256 + +/* 0x6500: Reserved */ + + TRAP(41) + .align 256 + +/* 0x6600: Reserved */ + + TRAP(42) + .align 256 + +/* 0x6700: Reserved */ + + TRAP(43) + .align 256 + +/* 0x6800: Reserved */ + + TRAP(44) + .align 256 + +/* 0x6900: IA-32 Exception vector */ + + TRAP(45) + .align 256 + +/* 0x6a00: IA-32 Intercept vector */ + + TRAP(46) + .align 256 + +/* 0x6b00: IA-32 Interrupt vector */ + + TRAP(47) + .align 256 + +/* 0x6c00: Reserved */ + + TRAP(48) + .align 256 + +/* 0x6d00: Reserved */ + + TRAP(49) + .align 256 + +/* 0x6e00: Reserved */ + + TRAP(50) + .align 256 + +/* 0x6f00: Reserved */ + + TRAP(51) + .align 256 + +/* 0x7000: Reserved */ + + TRAP(52) + .align 256 + +/* 0x7100: Reserved */ + + TRAP(53) + .align 256 + +/* 0x7200: Reserved */ + + TRAP(54) + .align 256 + +/* 0x7300: Reserved */ + + TRAP(55) + .align 256 + +/* 0x7400: Reserved */ + + TRAP(56) + .align 256 + +/* 0x7500: Reserved */ + + TRAP(57) + .align 256 + +/* 0x7600: Reserved */ + + TRAP(58) + .align 256 + +/* 0x7700: Reserved */ + + TRAP(59) + .align 256 + +/* 0x7800: Reserved */ + + TRAP(60) + .align 256 + +/* 0x7900: Reserved */ + + TRAP(61) + .align 256 + +/* 0x7a00: Reserved */ + + TRAP(62) + .align 256 + +/* 0x7b00: Reserved */ + + TRAP(63) + .align 256 + +/* 0x7c00: Reserved */ + + TRAP(64) + .align 256 + +/* 0x7d00: Reserved */ + + TRAP(65) + .align 256 + +/* 0x7e00: Reserved */ + + TRAP(66) + .align 256 + +/* 0x7f00: Reserved */ + + TRAP(67) + .align 256 + + .section .data.vhpt,"aw" + + .global ia64_vhpt + + .align 32768 +ia64_vhpt: .quad 0 + .align 32768 + + .text + +#define rIIP r31 +#define rIPSR r30 +#define rISR r29 +#define rIFA r28 +#define rPR r27 +#define rSP r26 +#define rIFS r25 +#define rR1 r24 +#define rR2 r23 +#define rBSPSTORE r22 +#define rRNAT r21 +#define rBSP r27 /* overlay rPR */ +#define rRSC r20 +#define rPFS r19 +#define rB0 r31 /* overlay rIIP */ + +/* + * exception_return: restore interrupted state + * + * Arguments: + * sp trapframe pointer + * + */ +LEAF(exception_return, 0) + + rsm psr.ic|psr.dt // disable interrupt collection and vm + ;; + srlz.d + dep r3=0,sp,61,3 // physical address + ;; + add r1=SIZEOF_TRAPFRAME-16,r3 // r1=&tf_f[FRAME_F15] + add r2=SIZEOF_TRAPFRAME-32,r3 // r2=&tf_f[FRAME_F14] + ;; + ldf.fill f15=[r1],-32 // r1=&tf_f[FRAME_F13] + ldf.fill f14=[r2],-32 // r2=&tf_f[FRAME_F12] + ;; + ldf.fill f13=[r1],-32 // r1=&tf_f[FRAME_F11] + ldf.fill f12=[r2],-32 // r2=&tf_f[FRAME_F10] + ;; + ldf.fill f11=[r1],-32 // r1=&tf_f[FRAME_F9] + ldf.fill f10=[r2],-32 // r2=&tf_f[FRAME_F8] + ;; + ldf.fill f9=[r1],-32 // r1=&tf_f[FRAME_F7] + ldf.fill f8=[r2],-32 // r2=&tf_f[FRAME_F6] + ;; + ldf.fill f7=[r1],-24 // r1=&tf_r[FRAME_R31] + ldf.fill f6=[r2],-24 // r2=&tf_r[FRAME_R30] + ;; + ld8.fill r31=[r1],-16 // r1=&tf_r[FRAME_R29] + ld8.fill r30=[r2],-16 // r2=&tf_r[FRAME_R28] + ;; + ld8.fill r29=[r1],-16 // r1=&tf_r[FRAME_R27] + ld8.fill r28=[r2],-16 // r2=&tf_r[FRAME_R26] + ;; + ld8.fill r27=[r1],-16 // r1=&tf_r[FRAME_R25] + ld8.fill r26=[r2],-16 // r2=&tf_r[FRAME_R24] + ;; + ld8.fill r25=[r1],-16 // r1=&tf_r[FRAME_R23] + ld8.fill r24=[r2],-16 // r2=&tf_r[FRAME_R22] + ;; + ld8.fill r23=[r1],-16 // r1=&tf_r[FRAME_R21] + ld8.fill r22=[r2],-16 // r2=&tf_r[FRAME_R20] + ;; + ld8.fill r21=[r1],-16 // r1=&tf_r[FRAME_R19] + ld8.fill r20=[r2],-16 // r2=&tf_r[FRAME_R18] + ;; + ld8.fill r19=[r1],-16 // r1=&tf_r[FRAME_R17] + ld8.fill r18=[r2],-16 // r2=&tf_r[FRAME_R16] + ;; + ld8.fill r17=[r1],-16 // r1=&tf_r[FRAME_R15] + ld8.fill r16=[r2],-16 // r2=&tf_r[FRAME_R14] + ;; + bsw.0 // switch to bank 0 + ;; + ld8.fill r15=[r1],-16 // r1=&tf_r[FRAME_R13] + ld8.fill r14=[r2],-16 // r2=&tf_r[FRAME_R12] + ;; + ld8.fill r13=[r1],-16 // r1=&tf_r[FRAME_R11] + ld8.fill r12=[r2],-16 // r2=&tf_r[FRAME_R10] + ;; + ld8.fill r11=[r1],-16 // r1=&tf_r[FRAME_R9] + ld8.fill r10=[r2],-16 // r2=&tf_r[FRAME_R8] + ;; + ld8.fill r9=[r1],-16 // r1=&tf_r[FRAME_R7] + ld8.fill r8=[r2],-16 // r2=&tf_r[FRAME_R6] + ;; + ld8.fill r7=[r1],-16 // r1=&tf_r[FRAME_R5] + ld8.fill r6=[r2],-16 // r2=&tf_r[FRAME_R4] + ;; + ld8.fill r5=[r1],-16 // r1=&tf_r[FRAME_R3] + ld8.fill r4=[r2],-16 // r2=&tf_r[FRAME_R2] + ;; + ld8.fill r3=[r1],-16 // r1=&tf_r[FRAME_R1] + ld8.fill rR2=[r2],-16 // r2=&tf_b[7] + ;; + ld8.fill rR1=[r1],-16 // r1=&tf_b[6] + ld8 r16=[r2],-16 // r2=&tf_b[5] + ;; + mov b7=r16 + ld8 r18=[r1],-16 // r1=&tf_b[4] + ld8 r19=[r2],-16 // r2=&tf_b[3] + ;; + mov b6=r18 + mov b5=r19 + ld8 r16=[r1],-16 // r1=&tf_b[2] + ld8 r17=[r2],-16 // r2=&tf_b[1] + ;; + mov b4=r16 + mov b3=r17 + ld8 r18=[r1],-16 // r1=&tf_b[0] + ld8 r19=[r2],-16 // r2=&tf_ar_fpsr + ;; + mov b2=r18 + mov b1=r19 + ld8 r16=[r1],-16 // r1=&tf_ar_ccv + ld8 r17=[r2],-16 // r2=&tf_ar_unat + ;; + mov b0=r16 + mov ar.fpsr=r17 + ld8 r18=[r1],-16 // r1=&tf_ar_bsp + ld8 r19=[r2],-16 // r2=&tf_ar_rnat + ;; + mov ar.ccv=r18 + mov ar.unat=r19 + ld8 rBSP=[r1],-16 // r1=&tf_ar_bspstore + ld8 rRNAT=[r2],-16 // r2=&tf_cr_ifs + ;; + ld8 rBSPSTORE=[r1],-16 // r1=&tf_cr_pfs + ld8 rIFS=[r2],-16 // r2=&tf_ar_rsc + ;; + ld8 rPFS=[r1],-16 // r1=&tf_pr + ld8 rRSC=[r2],-16 // r2=&tf_cr_ifa + ;; + ld8 rPR=[r1],-16 // r1=&tf_cr_isr + ld8 rIFA=[r2],-16 // r2=&tf_cr_ipsr + ;; + ld8 rIIP=[r1] + ld8 rIPSR=[r2] + ;; + extr.u r16=rIPSR,32,2 // extract ipsr.cpl + ;; + cmp.eq p1,p2=r0,r17 // test for kernel mode + ;; +(p2) br.cond.dpnt.few 1f // don't switch bs if not user + ;; + sub r16=rBSP,rBSPSTORE // how many bytes to load? + ;; + shl r16=r16,16 // value for ar.rsc + ;; + mov ar.rsc=r16 // setup for loadrs + ;; + loadrs // load user regs from kernel bs + ;; + mov ar.bspstore=rBSPSTORE + ;; + mov ar.rnat=rRNAT + +1: mov r1=rR1 + mov r2=rR2 + mov cr.ifs=rIFS + mov ar.rsc=rRSC + mov pr=rPR,0x1ffff + mov cr.ifa=rIFA + mov cr.iip=rIIP + mov cr.ipsr=rIPSR + ;; + rfi + + END(exception_return) + + +/* + * exception_save_regs: save interrupted state + * + * Arguments: + * b0 return address + * r16 saved b0 + * + * Return: + * sp kernel stack pointer + */ +LEAF(exception_save_regs, 0) + rsm psr.dt // turn off data translations + ;; + srlz.d // serialize + ;; + mov rIIP=cr.iip + mov rIPSR=cr.ipsr + mov rISR=cr.isr + mov rIFA=cr.ifa + mov rPR=pr + ;; + extr.u r17=rIPSR,32,2 // extract ipsr.cpl + ;; + cmp.eq p1,p2=r0,r17 // test for kernel mode + ;; + mov rSP=sp // save sp + ;; +(p2) mov sp=ar.k6 // and switch to kernel stack + mov r16=SIZEOF_TRAPFRAME + ;; + sub sp=sp,r16 // reserve trapframe + ;; + mov rR1=r1 + mov rR2=r2 + ;; + dep r1=0,sp,61,3 // r1=&tf_cr_iip + ;; + add r2=8,r1 // r2=&tf_cr_ipsr + ;; + st8 [r1]=rIIP,16 // r1=&tf_cr_isr + st8 [r2]=rIPSR,16 // r2=&tf_cr_ifa + ;; + st8 [r1]=rISR,16 // r1=&tf_pr + st8 [r2]=rIFA,16 // r2=&tf_ar_rsc + ;; + st8 [r1]=rPR,16 // r1=&tf_cr_pfs + + mov rB0=r16 + mov rRSC=ar.rsc + mov rPFS=ar.pfs + cover +(p2) mov r16=ar.k7 // curproc + mov rIFS=cr.ifs + ;; +(p2) add r16=P_ADDR,r16 // &curproc->p_addr + mov ar.rsc=0 + ;; +(p2) ld8 r16=[r16] // curproc->p_addr + mov rBSPSTORE=ar.bspstore + ;; +(p2) add r16=SIZEOF_USER,r16 // kernel backing store + mov rRNAT=ar.rnat + mov rBSP=ar.bsp + ;; +(p2) mov ar.bspstore=r16 // switch bspstore + st8 [r2]=rRSC,16 // r2=&tf_cr_ifs + ;; + st8 [r1]=rPFS,16 // r1=&tf_ar_bspstore + st8 [r2]=rIFS,16 // r2=&tf_ar_rnat + ;; + st8 [r1]=rBSPSTORE,16 // r1=&tf_ar_bsp + st8 [r2]=rRNAT,16 // r2=&tf_ar_unat + ;; + st8 [r1]=rBSP,16 // r1=&tf_ar_ccv + mov ar.rsc=3 // switch RSE back on + mov r16=ar.unat + ;; + mov r17=ar.ccv + st8 [r2]=r16,16 // r2=&tf_ar_fpsr + mov r18=ar.fpsr + ;; + st8 [r1]=r17,16 // r1=&tf_b[0] + st8 [r2]=r18,16 // r2=&tf_b[1] + mov r17=b1 + ;; + st8 [r1]=rB0,16 // r1=&tf_b[2] + mov r18=b2 + st8 [r2]=r17,16 // r2=&tf_b[3] + ;; + mov r17=b3 + st8 [r1]=r18,16 // r1=&tf_b[4] + ;; + mov r18=b4 + st8 [r2]=r17,16 // r2=&tf_b[5] + ;; + mov r17=b5 + st8 [r1]=r18,16 // r1=&tf_b[6] + ;; + mov r18=b6 + st8 [r2]=r17,16 // r2=&tf_b[7] + ;; + mov r17=b7 + st8 [r1]=r18,16 // r1=&tf_r[FRAME_R1] + ;; + st8 [r2]=r17,16 // r2=&tf_r[FRAME_R2] + ;; + .mem.offset 0,0 + st8.spill [r1]=rR1,16 // r1=&tf_r[FRAME_R3] + .mem.offset 8,0 + st8.spill [r2]=rR2,16 // r2=&tf_r[FRAME_R4] + ;; + .mem.offset 0,0 + st8.spill [r1]=r3,16 // r1=&tf_r[FRAME_R5] + .mem.offset 8,0 + st8.spill [r2]=r4,16 // r2=&tf_r[FRAME_R6] + ;; + .mem.offset 0,0 + st8.spill [r1]=r5,16 // r1=&tf_r[FRAME_R7] + .mem.offset 8,0 + st8.spill [r2]=r6,16 // r2=&tf_r[FRAME_R8] + ;; + .mem.offset 0,0 + st8.spill [r1]=r7,16 // r1=&tf_r[FRAME_R9] + .mem.offset 8,0 + st8.spill [r2]=r8,16 // r2=&tf_r[FRAME_R10] + ;; + .mem.offset 0,0 + st8.spill [r1]=r9,16 // r1=&tf_r[FRAME_R11] + .mem.offset 8,0 + st8.spill [r2]=r10,16 // r2=&tf_r[FRAME_SP] + ;; + .mem.offset 0,0 + st8.spill [r1]=r11,16 // r1=&tf_r[FRAME_R13] + .mem.offset 8,0 + st8.spill [r2]=rSP,16 // r2=&tf_r[FRAME_R14] + ;; + .mem.offset 0,0 + st8.spill [r1]=r13,16 // r1=&tf_r[FRAME_R15] + .mem.offset 8,0 + st8.spill [r2]=r14,16 // r2=&tf_r[FRAME_R16] + ;; + .mem.offset 0,0 + st8.spill [r1]=r15,16 // r1=&tf_r[FRAME_R17] + ;; + bsw.1 // switch to bank 1 + ;; + .mem.offset 8,0 + st8.spill [r2]=r16,16 // r2=&tf_r[FRAME_R18] + .mem.offset 0,0 + st8.spill [r1]=r17,16 // r1=&tf_r[FRAME_R19] + ;; + .mem.offset 8,0 + st8.spill [r2]=r18,16 // r2=&tf_r[FRAME_R20] + .mem.offset 0,0 + st8.spill [r1]=r19,16 // r1=&tf_r[FRAME_R21] + ;; + .mem.offset 8,0 + st8.spill [r2]=r20,16 // r2=&tf_r[FRAME_R22] + .mem.offset 0,0 + st8.spill [r1]=r21,16 // r1=&tf_r[FRAME_R23] + ;; + .mem.offset 8,0 + st8.spill [r2]=r22,16 // r2=&tf_r[FRAME_R24] + .mem.offset 0,0 + st8.spill [r1]=r23,16 // r1=&tf_r[FRAME_R25] + ;; + .mem.offset 8,0 + st8.spill [r2]=r24,16 // r2=&tf_r[FRAME_R26] + .mem.offset 0,0 + st8.spill [r1]=r25,16 // r1=&tf_r[FRAME_R27] + ;; + .mem.offset 8,0 + st8.spill [r2]=r26,16 // r2=&tf_r[FRAME_R28] + .mem.offset 0,0 + st8.spill [r1]=r27,16 // r1=&tf_r[FRAME_R29] + ;; + .mem.offset 8,0 + st8.spill [r2]=r28,16 // r2=&tf_r[FRAME_R30] + .mem.offset 0,0 + st8.spill [r1]=r29,16 // r1=&tf_r[FRAME_R31] + ;; + .mem.offset 8,0 + st8.spill [r2]=r30,24 // r2=&tf_f[FRAME_F6] + .mem.offset 0,0 + st8.spill [r1]=r31,32 // r1=&tf_f[FRAME_F7] + ;; + stf.spill [r2]=f6,32 // r2=&tf_f[FRAME_F8] + stf.spill [r1]=f7,32 // r1=&tf_f[FRAME_F9] + ;; + stf.spill [r2]=f8,32 // r2=&tf_f[FRAME_F10] + stf.spill [r1]=f9,32 // r1=&tf_f[FRAME_F11] + ;; + stf.spill [r2]=f10,32 // r2=&tf_f[FRAME_F12] + stf.spill [r1]=f11,32 // r1=&tf_f[FRAME_F13] + ;; + stf.spill [r2]=f12,32 // r2=&tf_f[FRAME_F14] + stf.spill [r1]=f13,32 // r1=&tf_f[FRAME_F15] + ;; + stf.spill [r2]=f14 // + stf.spill [r1]=f15 // + ;; + movl r1=__gp // kernel globals + ssm psr.ic|psr.dt // enable interrupts & translation + ;; + srlz.d // serialize + + br.ret.sptk.few b0 + + END(exception_save_regs) + + diff --git a/sys/ia64/ia64/exception.s b/sys/ia64/ia64/exception.s new file mode 100644 index 0000000..0f06ef0 --- /dev/null +++ b/sys/ia64/ia64/exception.s @@ -0,0 +1,949 @@ +/*- + * 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 <machine/asm.h> +#include <machine/pmap.h> +#include <assym.s> + +/* + * ar.k7 = curproc + * ar.k6 = ksp + */ + +/* + * Call exception_save_regs to preserve the interrupted state in a + * trapframe and call trap() with the value of _n_ as an argument. We + * arrange for trap() to return to exception_return which will restore + * the interrupted state before executing an rfi to resume it. + */ +#define TRAP(_n_) \ + mov r16=b0; \ + br.call.sptk.few b0=exception_save_regs; \ + alloc r16=ar.pfs,0,0,2,0; \ + movl r17=exception_return; \ + mov out0=_n_; \ + mov out1=sp;; \ + mov rp=r17; \ + br.call.sptk.few b6=trap + +/* + * The IA64 Interrupt Vector Table (IVT) contains 20 slots with 64 + * bundles per vector and 48 slots with 16 bundles per vector. + */ + + .section .text.ivt,"ax" + + .align 32768 + .global ia64_vector_table +ia64_vector_table: + +/* 0x0000: VHPT Translation vector */ + + TRAP(0) + .align 1024 + +/* 0x0400: Instruction TLB vector */ + + mov r16=cr.ifa + mov r17=pr + ;; + thash r18=r16 + ttag r19=r16 + ;; + add r20=24,r18 // collision chain + ;; + ld8 r20=[r20] // first entry + ;; + rsm psr.dt // turn off data translations + ;; + srlz.d // serialize + ;; +1: cmp.eq p1,p2=r0,r20 // done? +(p1) br.cond.spnt.few 9f // bail if done + ;; + add r21=16,r20 // tag location + ;; + ld8 r21=[r21] // read tag + ;; + cmp.eq p1,p2=r21,r19 // compare tags +(p2) br.cond.sptk.few 2f // if not, read next in chain + ;; + ld8 r21=[r20],8 // read pte + ;; + ld8 r22=[r20] // read rest of pte + ;; + dep r18=0,r18,61,3 // convert vhpt ptr to physical + ;; + add r20=16,r18 // address of tag + ;; + ld8.acq r23=[r20] // read old tag + movl r24=(1<<63) // ti bit + ;; + or r23=r23,r24 // set ti bit + ;; + st8.rel [r20]=r23 // store old tag + ti + ;; + mf // make sure everyone sees + ;; + st8 [r18]=r21,8 // store pte + ;; + st8 [r18]=r22,8 + ;; + st8.rel [r18]=r19 // store new tag + ;; + mov pr=r17,0x1ffff // restore predicates + ;; + rfi // walker will retry the access + +2: add r20=24,r20 // next in chain + ;; + ld8 r20=[r20] // read chain + br.cond.sptk.few 1b // loop + +9: mov pr=r17,0x1ffff // restore predicates + TRAP(1) // die horribly + + .align 1024 + +/* 0x0800: Data TLB vector */ + + mov r16=cr.ifa + mov r17=pr + ;; + thash r18=r16 + ttag r19=r16 + ;; + add r20=24,r18 // collision chain + ;; + ld8 r20=[r20] // first entry + ;; + rsm psr.dt // turn off data translations + ;; + srlz.d // serialize + ;; +1: cmp.eq p1,p2=r0,r20 // done? +(p1) br.cond.spnt.few 9f // bail if done + ;; + add r21=16,r20 // tag location + ;; + ld8 r21=[r21] // read tag + ;; + cmp.eq p1,p2=r21,r19 // compare tags +(p2) br.cond.sptk.few 2f // if not, read next in chain + ;; + ld8 r21=[r20],8 // read pte + ;; + ld8 r22=[r20] // read rest of pte + ;; + dep r18=0,r18,61,3 // convert vhpt ptr to physical + ;; + add r20=16,r18 // address of tag + ;; + ld8.acq r23=[r20] // read old tag + movl r24=(1<<63) // ti bit + ;; + or r23=r23,r24 // set ti bit + ;; + st8.rel [r20]=r23 // store old tag + ti + ;; + mf // make sure everyone sees + ;; + st8 [r18]=r21,8 // store pte + ;; + st8 [r18]=r22,8 + ;; + st8.rel [r18]=r19 // store new tag + ;; + mov pr=r17,0x1ffff // restore predicates + ;; + rfi // walker will retry the access + +2: add r20=24,r20 // next in chain + ;; + ld8 r20=[r20] // read chain + br.cond.sptk.few 1b // loop + +9: mov pr=r17,0x1ffff // restore predicates + TRAP(2) // die horribly + + .align 1024 + +/* 0x0c00: Alternate Instruction TLB vector */ + + mov r16=cr.ifa // where did it happen + ;; + mov r18=pr // save predicates + ;; + extr.u r17=r16,61,3 // get region number + ;; + cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 + ;; +(p1) movl r17=PTE_P+PTE_MA_WC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX +(p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RX + ;; + dep r16=0,r16,50,14 // clear bits above PPN + ;; + dep r16=r17,r17,0,12 // put pte bits in 0..11 + ;; + itc.i r16 + mov pr=r18,0x1ffff // restore predicates + ;; + rfi + + .align 1024 + +/* 0x1000: Alternate Data TLB vector */ + + mov r16=cr.ifa // where did it happen + mov r18=pr // save predicates + ;; + extr.u r17=r16,61,3 // get region number + ;; + cmp.eq p1,p2=7,r17 // RR7->p1, RR6->p2 + ;; +(p1) movl r17=PTE_P+PTE_MA_WC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW +(p2) movl r17=PTE_P+PTE_MA_UC+PTE_A+PTE_D+PTE_PL_KERN+PTE_AR_RW + ;; + dep r16=0,r16,50,14 // clear bits above PPN + ;; + dep r16=r17,r17,0,12 // put pte bits in 0..11 + ;; + itc.d r16 + mov pr=r18,0x1ffff // restore predicates + ;; + rfi + + .align 1024 + +/* 0x1400: Data Nested TLB vector */ + + TRAP(5) + .align 1024 + +/* 0x1800: Instruction Key Miss vector */ + + TRAP(6) + .align 1024 + +/* 0x1c00: Data Key Miss vector */ + + TRAP(7) + .align 1024 + +/* 0x2000: Dirty-Bit vector */ + + TRAP(8) + .align 1024 + +/* 0x2400: Instruction Access-Bit vector */ + + TRAP(9) + .align 1024 + +/* 0x2800: Data Access-Bit vector */ + + TRAP(10) + .align 1024 + +/* 0x2c00: Break Instruction vector */ + + TRAP(11) + .align 1024 + +/* 0x3000: External Interrupt vector */ + + TRAP(12) + .align 1024 + +/* 0x3400: Reserved */ + + TRAP(13) + .align 1024 + +/* 0x3800: Reserved */ + + TRAP(14) + .align 1024 + +/* 0x3c00: Reserved */ + + TRAP(15) + .align 1024 + +/* 0x4000: Reserved */ + + TRAP(16) + .align 1024 + +/* 0x4400: Reserved */ + + TRAP(17) + .align 1024 + +/* 0x4800: Reserved */ + + TRAP(18) + .align 1024 + +/* 0x4c00: Reserved */ + + TRAP(19) + .align 1024 + +/* 0x5000: Page Not Present vector */ + + TRAP(20) + .align 256 + +/* 0x5100: Key Permission vector */ + + TRAP(21) + .align 256 + +/* 0x5200: Instruction Access Rights vector */ + + TRAP(22) + .align 256 + +/* 0x5300: Data Access Rights vector */ + + TRAP(23) + .align 256 + +/* 0x5400: General Exception vector */ + + TRAP(24) + .align 256 + +/* 0x5500: Disabled FP-Register vector */ + + TRAP(25) + .align 256 + +/* 0x5600: NaT Consumption vector */ + + TRAP(26) + .align 256 + +/* 0x5700: Speculation vector */ + + TRAP(27) + .align 256 + +/* 0x5800: Reserved */ + + TRAP(28) + .align 256 + +/* 0x5900: Debug vector */ + + TRAP(29) + .align 256 + +/* 0x5a00: Unaligned Reference vector */ + + TRAP(30) + .align 256 + +/* 0x5b00: Unsupported Data Reference vector */ + + TRAP(31) + .align 256 + +/* 0x5c00: Floating-point Fault vector */ + + TRAP(32) + .align 256 + +/* 0x5d00: Floating-point Trap vector */ + + TRAP(33) + .align 256 + +/* 0x5e00: Lower-Privilege Transfer Trap vector */ + + TRAP(34) + .align 256 + +/* 0x5f00: Taken Branch Trap vector */ + + TRAP(35) + .align 256 + +/* 0x6000: Single Step Trap vector */ + + TRAP(36) + .align 256 + +/* 0x6100: Reserved */ + + TRAP(37) + .align 256 + +/* 0x6200: Reserved */ + + TRAP(38) + .align 256 + +/* 0x6300: Reserved */ + + TRAP(39) + .align 256 + +/* 0x6400: Reserved */ + + TRAP(40) + .align 256 + +/* 0x6500: Reserved */ + + TRAP(41) + .align 256 + +/* 0x6600: Reserved */ + + TRAP(42) + .align 256 + +/* 0x6700: Reserved */ + + TRAP(43) + .align 256 + +/* 0x6800: Reserved */ + + TRAP(44) + .align 256 + +/* 0x6900: IA-32 Exception vector */ + + TRAP(45) + .align 256 + +/* 0x6a00: IA-32 Intercept vector */ + + TRAP(46) + .align 256 + +/* 0x6b00: IA-32 Interrupt vector */ + + TRAP(47) + .align 256 + +/* 0x6c00: Reserved */ + + TRAP(48) + .align 256 + +/* 0x6d00: Reserved */ + + TRAP(49) + .align 256 + +/* 0x6e00: Reserved */ + + TRAP(50) + .align 256 + +/* 0x6f00: Reserved */ + + TRAP(51) + .align 256 + +/* 0x7000: Reserved */ + + TRAP(52) + .align 256 + +/* 0x7100: Reserved */ + + TRAP(53) + .align 256 + +/* 0x7200: Reserved */ + + TRAP(54) + .align 256 + +/* 0x7300: Reserved */ + + TRAP(55) + .align 256 + +/* 0x7400: Reserved */ + + TRAP(56) + .align 256 + +/* 0x7500: Reserved */ + + TRAP(57) + .align 256 + +/* 0x7600: Reserved */ + + TRAP(58) + .align 256 + +/* 0x7700: Reserved */ + + TRAP(59) + .align 256 + +/* 0x7800: Reserved */ + + TRAP(60) + .align 256 + +/* 0x7900: Reserved */ + + TRAP(61) + .align 256 + +/* 0x7a00: Reserved */ + + TRAP(62) + .align 256 + +/* 0x7b00: Reserved */ + + TRAP(63) + .align 256 + +/* 0x7c00: Reserved */ + + TRAP(64) + .align 256 + +/* 0x7d00: Reserved */ + + TRAP(65) + .align 256 + +/* 0x7e00: Reserved */ + + TRAP(66) + .align 256 + +/* 0x7f00: Reserved */ + + TRAP(67) + .align 256 + + .section .data.vhpt,"aw" + + .global ia64_vhpt + + .align 32768 +ia64_vhpt: .quad 0 + .align 32768 + + .text + +#define rIIP r31 +#define rIPSR r30 +#define rISR r29 +#define rIFA r28 +#define rPR r27 +#define rSP r26 +#define rIFS r25 +#define rR1 r24 +#define rR2 r23 +#define rBSPSTORE r22 +#define rRNAT r21 +#define rBSP r27 /* overlay rPR */ +#define rRSC r20 +#define rPFS r19 +#define rB0 r31 /* overlay rIIP */ + +/* + * exception_return: restore interrupted state + * + * Arguments: + * sp trapframe pointer + * + */ +LEAF(exception_return, 0) + + rsm psr.ic|psr.dt // disable interrupt collection and vm + ;; + srlz.d + dep r3=0,sp,61,3 // physical address + ;; + add r1=SIZEOF_TRAPFRAME-16,r3 // r1=&tf_f[FRAME_F15] + add r2=SIZEOF_TRAPFRAME-32,r3 // r2=&tf_f[FRAME_F14] + ;; + ldf.fill f15=[r1],-32 // r1=&tf_f[FRAME_F13] + ldf.fill f14=[r2],-32 // r2=&tf_f[FRAME_F12] + ;; + ldf.fill f13=[r1],-32 // r1=&tf_f[FRAME_F11] + ldf.fill f12=[r2],-32 // r2=&tf_f[FRAME_F10] + ;; + ldf.fill f11=[r1],-32 // r1=&tf_f[FRAME_F9] + ldf.fill f10=[r2],-32 // r2=&tf_f[FRAME_F8] + ;; + ldf.fill f9=[r1],-32 // r1=&tf_f[FRAME_F7] + ldf.fill f8=[r2],-32 // r2=&tf_f[FRAME_F6] + ;; + ldf.fill f7=[r1],-24 // r1=&tf_r[FRAME_R31] + ldf.fill f6=[r2],-24 // r2=&tf_r[FRAME_R30] + ;; + ld8.fill r31=[r1],-16 // r1=&tf_r[FRAME_R29] + ld8.fill r30=[r2],-16 // r2=&tf_r[FRAME_R28] + ;; + ld8.fill r29=[r1],-16 // r1=&tf_r[FRAME_R27] + ld8.fill r28=[r2],-16 // r2=&tf_r[FRAME_R26] + ;; + ld8.fill r27=[r1],-16 // r1=&tf_r[FRAME_R25] + ld8.fill r26=[r2],-16 // r2=&tf_r[FRAME_R24] + ;; + ld8.fill r25=[r1],-16 // r1=&tf_r[FRAME_R23] + ld8.fill r24=[r2],-16 // r2=&tf_r[FRAME_R22] + ;; + ld8.fill r23=[r1],-16 // r1=&tf_r[FRAME_R21] + ld8.fill r22=[r2],-16 // r2=&tf_r[FRAME_R20] + ;; + ld8.fill r21=[r1],-16 // r1=&tf_r[FRAME_R19] + ld8.fill r20=[r2],-16 // r2=&tf_r[FRAME_R18] + ;; + ld8.fill r19=[r1],-16 // r1=&tf_r[FRAME_R17] + ld8.fill r18=[r2],-16 // r2=&tf_r[FRAME_R16] + ;; + ld8.fill r17=[r1],-16 // r1=&tf_r[FRAME_R15] + ld8.fill r16=[r2],-16 // r2=&tf_r[FRAME_R14] + ;; + bsw.0 // switch to bank 0 + ;; + ld8.fill r15=[r1],-16 // r1=&tf_r[FRAME_R13] + ld8.fill r14=[r2],-16 // r2=&tf_r[FRAME_R12] + ;; + ld8.fill r13=[r1],-16 // r1=&tf_r[FRAME_R11] + ld8.fill r12=[r2],-16 // r2=&tf_r[FRAME_R10] + ;; + ld8.fill r11=[r1],-16 // r1=&tf_r[FRAME_R9] + ld8.fill r10=[r2],-16 // r2=&tf_r[FRAME_R8] + ;; + ld8.fill r9=[r1],-16 // r1=&tf_r[FRAME_R7] + ld8.fill r8=[r2],-16 // r2=&tf_r[FRAME_R6] + ;; + ld8.fill r7=[r1],-16 // r1=&tf_r[FRAME_R5] + ld8.fill r6=[r2],-16 // r2=&tf_r[FRAME_R4] + ;; + ld8.fill r5=[r1],-16 // r1=&tf_r[FRAME_R3] + ld8.fill r4=[r2],-16 // r2=&tf_r[FRAME_R2] + ;; + ld8.fill r3=[r1],-16 // r1=&tf_r[FRAME_R1] + ld8.fill rR2=[r2],-16 // r2=&tf_b[7] + ;; + ld8.fill rR1=[r1],-16 // r1=&tf_b[6] + ld8 r16=[r2],-16 // r2=&tf_b[5] + ;; + mov b7=r16 + ld8 r18=[r1],-16 // r1=&tf_b[4] + ld8 r19=[r2],-16 // r2=&tf_b[3] + ;; + mov b6=r18 + mov b5=r19 + ld8 r16=[r1],-16 // r1=&tf_b[2] + ld8 r17=[r2],-16 // r2=&tf_b[1] + ;; + mov b4=r16 + mov b3=r17 + ld8 r18=[r1],-16 // r1=&tf_b[0] + ld8 r19=[r2],-16 // r2=&tf_ar_fpsr + ;; + mov b2=r18 + mov b1=r19 + ld8 r16=[r1],-16 // r1=&tf_ar_ccv + ld8 r17=[r2],-16 // r2=&tf_ar_unat + ;; + mov b0=r16 + mov ar.fpsr=r17 + ld8 r18=[r1],-16 // r1=&tf_ar_bsp + ld8 r19=[r2],-16 // r2=&tf_ar_rnat + ;; + mov ar.ccv=r18 + mov ar.unat=r19 + ld8 rBSP=[r1],-16 // r1=&tf_ar_bspstore + ld8 rRNAT=[r2],-16 // r2=&tf_cr_ifs + ;; + ld8 rBSPSTORE=[r1],-16 // r1=&tf_cr_pfs + ld8 rIFS=[r2],-16 // r2=&tf_ar_rsc + ;; + ld8 rPFS=[r1],-16 // r1=&tf_pr + ld8 rRSC=[r2],-16 // r2=&tf_cr_ifa + ;; + ld8 rPR=[r1],-16 // r1=&tf_cr_isr + ld8 rIFA=[r2],-16 // r2=&tf_cr_ipsr + ;; + ld8 rIIP=[r1] + ld8 rIPSR=[r2] + ;; + extr.u r16=rIPSR,32,2 // extract ipsr.cpl + ;; + cmp.eq p1,p2=r0,r17 // test for kernel mode + ;; +(p2) br.cond.dpnt.few 1f // don't switch bs if not user + ;; + sub r16=rBSP,rBSPSTORE // how many bytes to load? + ;; + shl r16=r16,16 // value for ar.rsc + ;; + mov ar.rsc=r16 // setup for loadrs + ;; + loadrs // load user regs from kernel bs + ;; + mov ar.bspstore=rBSPSTORE + ;; + mov ar.rnat=rRNAT + +1: mov r1=rR1 + mov r2=rR2 + mov cr.ifs=rIFS + mov ar.rsc=rRSC + mov pr=rPR,0x1ffff + mov cr.ifa=rIFA + mov cr.iip=rIIP + mov cr.ipsr=rIPSR + ;; + rfi + + END(exception_return) + + +/* + * exception_save_regs: save interrupted state + * + * Arguments: + * b0 return address + * r16 saved b0 + * + * Return: + * sp kernel stack pointer + */ +LEAF(exception_save_regs, 0) + rsm psr.dt // turn off data translations + ;; + srlz.d // serialize + ;; + mov rIIP=cr.iip + mov rIPSR=cr.ipsr + mov rISR=cr.isr + mov rIFA=cr.ifa + mov rPR=pr + ;; + extr.u r17=rIPSR,32,2 // extract ipsr.cpl + ;; + cmp.eq p1,p2=r0,r17 // test for kernel mode + ;; + mov rSP=sp // save sp + ;; +(p2) mov sp=ar.k6 // and switch to kernel stack + mov r16=SIZEOF_TRAPFRAME + ;; + sub sp=sp,r16 // reserve trapframe + ;; + mov rR1=r1 + mov rR2=r2 + ;; + dep r1=0,sp,61,3 // r1=&tf_cr_iip + ;; + add r2=8,r1 // r2=&tf_cr_ipsr + ;; + st8 [r1]=rIIP,16 // r1=&tf_cr_isr + st8 [r2]=rIPSR,16 // r2=&tf_cr_ifa + ;; + st8 [r1]=rISR,16 // r1=&tf_pr + st8 [r2]=rIFA,16 // r2=&tf_ar_rsc + ;; + st8 [r1]=rPR,16 // r1=&tf_cr_pfs + + mov rB0=r16 + mov rRSC=ar.rsc + mov rPFS=ar.pfs + cover +(p2) mov r16=ar.k7 // curproc + mov rIFS=cr.ifs + ;; +(p2) add r16=P_ADDR,r16 // &curproc->p_addr + mov ar.rsc=0 + ;; +(p2) ld8 r16=[r16] // curproc->p_addr + mov rBSPSTORE=ar.bspstore + ;; +(p2) add r16=SIZEOF_USER,r16 // kernel backing store + mov rRNAT=ar.rnat + mov rBSP=ar.bsp + ;; +(p2) mov ar.bspstore=r16 // switch bspstore + st8 [r2]=rRSC,16 // r2=&tf_cr_ifs + ;; + st8 [r1]=rPFS,16 // r1=&tf_ar_bspstore + st8 [r2]=rIFS,16 // r2=&tf_ar_rnat + ;; + st8 [r1]=rBSPSTORE,16 // r1=&tf_ar_bsp + st8 [r2]=rRNAT,16 // r2=&tf_ar_unat + ;; + st8 [r1]=rBSP,16 // r1=&tf_ar_ccv + mov ar.rsc=3 // switch RSE back on + mov r16=ar.unat + ;; + mov r17=ar.ccv + st8 [r2]=r16,16 // r2=&tf_ar_fpsr + mov r18=ar.fpsr + ;; + st8 [r1]=r17,16 // r1=&tf_b[0] + st8 [r2]=r18,16 // r2=&tf_b[1] + mov r17=b1 + ;; + st8 [r1]=rB0,16 // r1=&tf_b[2] + mov r18=b2 + st8 [r2]=r17,16 // r2=&tf_b[3] + ;; + mov r17=b3 + st8 [r1]=r18,16 // r1=&tf_b[4] + ;; + mov r18=b4 + st8 [r2]=r17,16 // r2=&tf_b[5] + ;; + mov r17=b5 + st8 [r1]=r18,16 // r1=&tf_b[6] + ;; + mov r18=b6 + st8 [r2]=r17,16 // r2=&tf_b[7] + ;; + mov r17=b7 + st8 [r1]=r18,16 // r1=&tf_r[FRAME_R1] + ;; + st8 [r2]=r17,16 // r2=&tf_r[FRAME_R2] + ;; + .mem.offset 0,0 + st8.spill [r1]=rR1,16 // r1=&tf_r[FRAME_R3] + .mem.offset 8,0 + st8.spill [r2]=rR2,16 // r2=&tf_r[FRAME_R4] + ;; + .mem.offset 0,0 + st8.spill [r1]=r3,16 // r1=&tf_r[FRAME_R5] + .mem.offset 8,0 + st8.spill [r2]=r4,16 // r2=&tf_r[FRAME_R6] + ;; + .mem.offset 0,0 + st8.spill [r1]=r5,16 // r1=&tf_r[FRAME_R7] + .mem.offset 8,0 + st8.spill [r2]=r6,16 // r2=&tf_r[FRAME_R8] + ;; + .mem.offset 0,0 + st8.spill [r1]=r7,16 // r1=&tf_r[FRAME_R9] + .mem.offset 8,0 + st8.spill [r2]=r8,16 // r2=&tf_r[FRAME_R10] + ;; + .mem.offset 0,0 + st8.spill [r1]=r9,16 // r1=&tf_r[FRAME_R11] + .mem.offset 8,0 + st8.spill [r2]=r10,16 // r2=&tf_r[FRAME_SP] + ;; + .mem.offset 0,0 + st8.spill [r1]=r11,16 // r1=&tf_r[FRAME_R13] + .mem.offset 8,0 + st8.spill [r2]=rSP,16 // r2=&tf_r[FRAME_R14] + ;; + .mem.offset 0,0 + st8.spill [r1]=r13,16 // r1=&tf_r[FRAME_R15] + .mem.offset 8,0 + st8.spill [r2]=r14,16 // r2=&tf_r[FRAME_R16] + ;; + .mem.offset 0,0 + st8.spill [r1]=r15,16 // r1=&tf_r[FRAME_R17] + ;; + bsw.1 // switch to bank 1 + ;; + .mem.offset 8,0 + st8.spill [r2]=r16,16 // r2=&tf_r[FRAME_R18] + .mem.offset 0,0 + st8.spill [r1]=r17,16 // r1=&tf_r[FRAME_R19] + ;; + .mem.offset 8,0 + st8.spill [r2]=r18,16 // r2=&tf_r[FRAME_R20] + .mem.offset 0,0 + st8.spill [r1]=r19,16 // r1=&tf_r[FRAME_R21] + ;; + .mem.offset 8,0 + st8.spill [r2]=r20,16 // r2=&tf_r[FRAME_R22] + .mem.offset 0,0 + st8.spill [r1]=r21,16 // r1=&tf_r[FRAME_R23] + ;; + .mem.offset 8,0 + st8.spill [r2]=r22,16 // r2=&tf_r[FRAME_R24] + .mem.offset 0,0 + st8.spill [r1]=r23,16 // r1=&tf_r[FRAME_R25] + ;; + .mem.offset 8,0 + st8.spill [r2]=r24,16 // r2=&tf_r[FRAME_R26] + .mem.offset 0,0 + st8.spill [r1]=r25,16 // r1=&tf_r[FRAME_R27] + ;; + .mem.offset 8,0 + st8.spill [r2]=r26,16 // r2=&tf_r[FRAME_R28] + .mem.offset 0,0 + st8.spill [r1]=r27,16 // r1=&tf_r[FRAME_R29] + ;; + .mem.offset 8,0 + st8.spill [r2]=r28,16 // r2=&tf_r[FRAME_R30] + .mem.offset 0,0 + st8.spill [r1]=r29,16 // r1=&tf_r[FRAME_R31] + ;; + .mem.offset 8,0 + st8.spill [r2]=r30,24 // r2=&tf_f[FRAME_F6] + .mem.offset 0,0 + st8.spill [r1]=r31,32 // r1=&tf_f[FRAME_F7] + ;; + stf.spill [r2]=f6,32 // r2=&tf_f[FRAME_F8] + stf.spill [r1]=f7,32 // r1=&tf_f[FRAME_F9] + ;; + stf.spill [r2]=f8,32 // r2=&tf_f[FRAME_F10] + stf.spill [r1]=f9,32 // r1=&tf_f[FRAME_F11] + ;; + stf.spill [r2]=f10,32 // r2=&tf_f[FRAME_F12] + stf.spill [r1]=f11,32 // r1=&tf_f[FRAME_F13] + ;; + stf.spill [r2]=f12,32 // r2=&tf_f[FRAME_F14] + stf.spill [r1]=f13,32 // r1=&tf_f[FRAME_F15] + ;; + stf.spill [r2]=f14 // + stf.spill [r1]=f15 // + ;; + movl r1=__gp // kernel globals + ssm psr.ic|psr.dt // enable interrupts & translation + ;; + srlz.d // serialize + + br.ret.sptk.few b0 + + END(exception_save_regs) + + diff --git a/sys/ia64/ia64/genassym.c b/sys/ia64/ia64/genassym.c new file mode 100644 index 0000000..e94a2ab --- /dev/null +++ b/sys/ia64/ia64/genassym.c @@ -0,0 +1,109 @@ +/*- + * 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. + * 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: @(#)genassym.c 5.11 (Berkeley) 5/10/91 + * $FreeBSD$ + */ + +#include <stddef.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/assym.h> +#include <sys/proc.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/errno.h> +#include <sys/proc.h> +#include <sys/mount.h> +#include <sys/socket.h> +#include <sys/resource.h> +#include <sys/resourcevar.h> +#include <sys/ucontext.h> +#include <machine/frame.h> +#include <machine/mutex.h> +#include <sys/vmmeter.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <sys/user.h> +#include <net/if.h> +#include <netinet/in.h> +#include <nfs/nfsv2.h> +#include <nfs/rpcv2.h> +#include <nfs/nfs.h> +#include <nfs/nfsdiskless.h> + +ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); +ASSYM(MTX_RECURSE, offsetof(struct mtx, mtx_recurse)); +ASSYM(MTX_SAVEPSR, offsetof(struct mtx, mtx_savepsr)); +ASSYM(MTX_UNOWNED, MTX_UNOWNED); + +ASSYM(P_ADDR, offsetof(struct proc, p_addr)); +ASSYM(P_MD_FLAGS, offsetof(struct proc, p_md.md_flags)); +ASSYM(P_MD_PCBPADDR, offsetof(struct proc, p_md.md_pcbpaddr)); + +ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS); + +ASSYM(SIZEOF_USER, sizeof(struct user)); + +ASSYM(U_PCB_R4, offsetof(struct user, u_pcb.pcb_r4)); +ASSYM(U_PCB_R5, offsetof(struct user, u_pcb.pcb_r5)); +ASSYM(U_PCB_R6, offsetof(struct user, u_pcb.pcb_r6)); +ASSYM(U_PCB_R7, offsetof(struct user, u_pcb.pcb_r7)); + +ASSYM(U_PCB_F2, offsetof(struct user, u_pcb.pcb_f2)); +ASSYM(U_PCB_F3, offsetof(struct user, u_pcb.pcb_f3)); +ASSYM(U_PCB_F4, offsetof(struct user, u_pcb.pcb_f4)); +ASSYM(U_PCB_F5, offsetof(struct user, u_pcb.pcb_f5)); + +ASSYM(U_PCB_OLD_UNAT, offsetof(struct user, u_pcb.pcb_old_unat)); +ASSYM(U_PCB_SP, offsetof(struct user, u_pcb.pcb_sp)); +ASSYM(U_PCB_PFS, offsetof(struct user, u_pcb.pcb_pfs)); +ASSYM(U_PCB_BSPSTORE, offsetof(struct user, u_pcb.pcb_bspstore)); + +ASSYM(U_PCB_UNAT, offsetof(struct user, u_pcb.pcb_unat)); +ASSYM(U_PCB_RNAT, offsetof(struct user, u_pcb.pcb_rnat)); +ASSYM(U_PCB_PR, offsetof(struct user, u_pcb.pcb_pr)); +ASSYM(U_PCB_IIP, offsetof(struct user, u_pcb.pcb_iip)); + +ASSYM(UC_MCONTEXT_MC_AR_BSP, offsetof(ucontext_t, uc_mcontext.mc_ar_bsp)); +ASSYM(UC_MCONTEXT_MC_AR_RNAT, offsetof(ucontext_t, uc_mcontext.mc_ar_rnat)); + +ASSYM(EFAULT, EFAULT); +ASSYM(ENAMETOOLONG, ENAMETOOLONG); + +ASSYM(SIZEOF_TRAPFRAME, sizeof(struct trapframe)); diff --git a/sys/ia64/ia64/genassym.sh b/sys/ia64/ia64/genassym.sh new file mode 100644 index 0000000..c8fd249 --- /dev/null +++ b/sys/ia64/ia64/genassym.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# $FreeBSD$ + +# Grrr, this should use stdin and stdout, but is encrufted for compatibility. + +usage() { + echo "usage: genassym [-o outfile] objfile" + exit 1 +} + +outfile=/dev/stdout +while getopts "o:" option +do + case "$option" in + o) outfile="$OPTARG";; + *) usage;; + esac +done +shift $(($OPTIND - 1)) +case $# in +1) ;; +*) usage;; +esac + +ia64-unknown-linux-nm "$1" | awk ' +/ C .*sign$/ { + sign = substr($1, length($1) - 3, 4) + sub("^0*", "", sign) + if (sign != "") + sign = "-" +} +/ C .*w0$/ { + w0 = substr($1, length($1) - 3, 4) +} +/ C .*w1$/ { + w1 = substr($1, length($1) - 3, 4) +} +/ C .*w2$/ { + w2 = substr($1, length($1) - 3, 4) +} +/ C .*w3$/ { + w3 = substr($1, length($1) - 3, 4) + w = w3 w2 w1 w0 + sub("^0*", "", w) + if (w == "") + w = "0" + sub("w3$", "", $3) + # This still has minor problems representing INT_MIN, etc. E.g., + # with 32-bit 2''s complement ints, this prints -0x80000000, which + # has the wrong type (unsigned int). + printf("#define\t%s\t%s0x%s\n", $3, sign, w) +} +' 3>"$outfile" >&3 3>&- diff --git a/sys/ia64/ia64/in_cksum.c b/sys/ia64/ia64/in_cksum.c new file mode 100644 index 0000000..4b7fca2 --- /dev/null +++ b/sys/ia64/ia64/in_cksum.c @@ -0,0 +1,249 @@ +/* $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[] = { + /*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 */ +}; + +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; +}; + +u_int64_t in_cksumdata __P((caddr_t buf, int len)); + +u_int64_t +in_cksumdata(buf, len) + register caddr_t buf; + register int len; +{ + const u_int32_t *lw = (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(m, len, 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 ^ (long) 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(ip) + const struct ip *ip; +{ + u_int64_t sum = in_cksumdata((caddr_t) ip, sizeof(struct ip)); + union q_util q_util; + union l_util l_util; + REDUCE16; + return (~sum & 0xffff); +} diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c new file mode 100644 index 0000000..ec0ac51 --- /dev/null +++ b/sys/ia64/ia64/interrupt.c @@ -0,0 +1,187 @@ +/* $FreeBSD$ */ +/* $NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Authors: Keith Bostic, 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. + */ +/* + * Additional Copyright (c) 1997 by Matthew Jacob for NASA/Ames Research Center. + * Redistribute and modify at will, leaving only this additional copyright + * notice. + */ + +#include "opt_ddb.h" + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +/* __KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $");*/ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/vmmeter.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/ktr.h> + +#include <machine/reg.h> +#include <machine/frame.h> +#include <machine/intr.h> +#include <machine/mutex.h> + +#ifdef EVCNT_COUNTERS +struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */ +#else +#include <machine/intrcnt.h> +#endif + +#ifdef DDB +#include <ddb/ddb.h> +#endif + +volatile int mc_expected, mc_received; + +static void +dummy_perf(unsigned long vector, struct trapframe *framep) +{ + printf("performance interrupt!\n"); +} + +void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf; + + +static u_int schedclk2; + +void +interrupt(a0, a1, a2, framep) + unsigned long a0, a1, a2; + struct trapframe *framep; +{ +#if 0 + /* + * Find our per-cpu globals. + */ + globalp = (struct globaldata *) alpha_pal_rdval(); + + atomic_add_int(&PCPU_GET(intr_nesting_level), 1); + { + struct proc* p = curproc; + if (!p) p = &proc0; + if ((caddr_t) framep < (caddr_t) p->p_addr + 1024) { + mtx_enter(&Giant, MTX_DEF); + panic("possible stack overflow\n"); + } + } + + framep->tf_regs[FRAME_TRAPARG_A0] = a0; + framep->tf_regs[FRAME_TRAPARG_A1] = a1; + framep->tf_regs[FRAME_TRAPARG_A2] = a2; + switch (a0) { + case ALPHA_INTR_XPROC: /* interprocessor interrupt */ + CTR0(KTR_INTR|KTR_SMP, "interprocessor interrupt"); + smp_handle_ipi(framep); /* note: lock not taken */ + break; + + case ALPHA_INTR_CLOCK: /* clock interrupt */ + CTR0(KTR_INTR, "clock interrupt"); + if (PCPU_GET(cpuno) != hwrpb->rpb_primary_cpu_id) { + CTR0(KTR_INTR, "ignoring clock on secondary"); + return; + } + + mtx_enter(&Giant, MTX_DEF); + cnt.v_intr++; +#ifdef EVCNT_COUNTERS + clock_intr_evcnt.ev_count++; +#else + intrcnt[INTRCNT_CLOCK]++; +#endif + if (platform.clockintr){ + (*platform.clockintr)(framep); + /* divide hz (1024) by 8 to get stathz (128) */ + if((++schedclk2 & 0x7) == 0) + statclock((struct clockframe *)framep); + } + mtx_exit(&Giant, MTX_DEF); + break; + + case ALPHA_INTR_ERROR: /* Machine Check or Correctable Error */ + mtx_enter(&Giant, MTX_DEF); + a0 = alpha_pal_rdmces(); + if (platform.mcheck_handler) + (*platform.mcheck_handler)(a0, framep, a1, a2); + else + machine_check(a0, framep, a1, a2); + mtx_exit(&Giant, MTX_DEF); + break; + + case ALPHA_INTR_DEVICE: /* I/O device interrupt */ + mtx_enter(&Giant, MTX_DEF); + cnt.v_intr++; + if (platform.iointr) + (*platform.iointr)(framep, a1); + mtx_exit(&Giant, MTX_DEF); + break; + + case ALPHA_INTR_PERF: /* interprocessor interrupt */ + mtx_enter(&Giant, MTX_DEF); + perf_irq(a1, framep); + mtx_exit(&Giant, MTX_DEF); + break; + + case ALPHA_INTR_PASSIVE: +#if 0 + printf("passive release interrupt vec 0x%lx (ignoring)\n", a1); +#endif + break; + + default: + mtx_enter(&Giant, MTX_DEF); + panic("unexpected interrupt: type 0x%lx vec 0x%lx a2 0x%lx\n", + a0, a1, a2); + /* NOTREACHED */ + } + atomic_subtract_int(&PCPU_GET(intr_nesting_level), 1); +#endif +} + + +int +badaddr(addr, size) + void *addr; + size_t size; +{ + return(badaddr_read(addr, size, NULL)); +} + +int +badaddr_read(addr, size, rptr) + void *addr; + size_t size; + void *rptr; +{ + return (1); /* XXX implement */ +} diff --git a/sys/ia64/ia64/ipl_funcs.c b/sys/ia64/ia64/ipl_funcs.c new file mode 100644 index 0000000..baf6cb2 --- /dev/null +++ b/sys/ia64/ia64/ipl_funcs.c @@ -0,0 +1,222 @@ +/*- + * 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$ + */ + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/ktr.h> +#include <sys/interrupt.h> +#include <machine/ipl.h> +#include <machine/cpu.h> +#include <machine/globaldata.h> +#include <machine/globals.h> +#include <machine/mutex.h> +#include <net/netisr.h> + +#include "sio.h" + +unsigned int bio_imask; /* XXX */ +unsigned int cam_imask; /* XXX */ +unsigned int net_imask; /* XXX */ +unsigned int tty_imask; /* XXX */ + +static void swi_net(void); + +void (*netisrs[32]) __P((void)); +swihand_t *ihandlers[32] = { /* software interrupts */ + swi_null, swi_net, swi_null, swi_null, + swi_null, softclock, swi_null, swi_null, + swi_null, swi_null, swi_null, swi_null, + swi_null, swi_null, swi_null, swi_null, + swi_null, swi_null, swi_null, swi_null, + swi_null, swi_null, swi_null, swi_null, + swi_null, swi_null, swi_null, swi_null, + swi_null, swi_null, swi_null, swi_null, +}; + +u_int32_t netisr; +u_int32_t ipending; +u_int32_t idelayed; + +#define getcpl() (alpha_pal_rdps() & ALPHA_PSL_IPL_MASK) + + +static void atomic_setbit(u_int32_t* p, u_int32_t bit) +{ + *p |= bit; +} + +static u_int32_t atomic_readandclear(u_int32_t* p) +{ + u_int32_t v = *p; + *p = 0; + return v; +} + +void +swi_null() +{ + /* No interrupt registered, do nothing */ +} + +void +swi_generic() +{ + /* Just a placeholder, we call swi_dispatcher directly */ + panic("swi_generic() called"); +} + +static void +swi_net() +{ + u_int32_t bits = atomic_readandclear(&netisr); + int i; + + for (i = 0; i < 32; i++) { + if (bits & 1) + netisrs[i](); + bits >>= 1; + } +} + +void +do_sir() +{ + u_int32_t pend; + int i; + + mtx_enter(&Giant, MTX_DEF); + + atomic_add_int(&PCPU_GET(intr_nesting_level), 1); + splsoft(); + while ((pend = atomic_readandclear(&ipending)) != 0) { + for (i = 0; pend && i < 32; i++) { + if (pend & (1 << i)) { + if (ihandlers[i] == swi_generic) + swi_dispatcher(i); + else + ihandlers[i](); + pend &= ~(1 << i); + } + } + } + atomic_subtract_int(&PCPU_GET(intr_nesting_level), 1); + + mtx_exit(&Giant, MTX_DEF); +} + +#define GENSET(name, ptr, bit) \ + \ +void name(void) \ +{ \ + atomic_setbit(ptr, bit); \ +} + +GENSET(setdelayed, &ipending, atomic_readandclear(&idelayed)) +GENSET(setsofttty, &ipending, 1 << SWI_TTY) +GENSET(setsoftnet, &ipending, 1 << SWI_NET) +GENSET(setsoftcamnet, &ipending, 1 << SWI_CAMNET) +GENSET(setsoftcambio, &ipending, 1 << SWI_CAMBIO) +GENSET(setsoftvm, &ipending, 1 << SWI_VM) +GENSET(setsofttq, &ipending, 1 << SWI_TQ) +GENSET(setsoftclock, &ipending, 1 << SWI_CLOCK) + +GENSET(schedsofttty, &idelayed, 1 << SWI_TTY) +GENSET(schedsoftnet, &idelayed, 1 << SWI_NET) +GENSET(schedsoftcamnet, &idelayed, 1 << SWI_CAMNET) +GENSET(schedsoftcambio, &idelayed, 1 << SWI_CAMBIO) +GENSET(schedsoftvm, &idelayed, 1 << SWI_VM) +GENSET(schedsofttq, &idelayed, 1 << SWI_TQ) +GENSET(schedsoftclock, &idelayed, 1 << SWI_CLOCK) + +#ifdef INVARIANT_SUPPORT + +#define SPLASSERT_IGNORE 0 +#define SPLASSERT_LOG 1 +#define SPLASSERT_PANIC 2 + +static int splassertmode = SPLASSERT_LOG; +SYSCTL_INT(_kern, OID_AUTO, splassertmode, CTLFLAG_RW, + &splassertmode, 0, "Set the mode of SPLASSERT"); + +static void +init_splassertmode(void *ignored) +{ + TUNABLE_INT_FETCH("kern.splassertmode", 0, splassertmode); +} +SYSINIT(param, SI_SUB_TUNABLES, SI_ORDER_ANY, init_splassertmode, NULL); + +static void +splassertfail(char *str, const char *msg, char *name, int level) +{ + switch (splassertmode) { + case SPLASSERT_IGNORE: + break; + case SPLASSERT_LOG: + printf(str, msg, name, level); + printf("\n"); + break; + case SPLASSERT_PANIC: + panic(str, msg, name, level); + break; + } +} + +#define GENSPLASSERT(name, pri) \ +void \ +name##assert(const char *msg) \ +{ \ + u_int cpl; \ + \ + cpl = getcpl(); \ + if (cpl < ALPHA_PSL_IPL_##pri) \ + splassertfail("%s: not %s, cpl == %#x", \ + msg, __XSTRING(name) + 3, cpl); \ +} +#else +#define GENSPLASSERT(name, pri) +#endif + +GENSPLASSERT(splbio, IO) +GENSPLASSERT(splcam, IO) +GENSPLASSERT(splclock, CLOCK) +GENSPLASSERT(splhigh, HIGH) +GENSPLASSERT(splimp, IO) +GENSPLASSERT(splnet, IO) +GENSPLASSERT(splsoftcam, SOFT) +GENSPLASSERT(splsoftcambio, SOFT) /* XXX no corresponding spl for alpha */ +GENSPLASSERT(splsoftcamnet, SOFT) /* XXX no corresponding spl for alpha */ +GENSPLASSERT(splsoftclock, SOFT) +GENSPLASSERT(splsofttty, SOFT) /* XXX no corresponding spl for alpha */ +GENSPLASSERT(splsoftvm, SOFT) +GENSPLASSERT(splsofttq, SOFT) +GENSPLASSERT(splstatclock, CLOCK) +GENSPLASSERT(spltty, IO) +GENSPLASSERT(splvm, IO) diff --git a/sys/ia64/ia64/locore.S b/sys/ia64/ia64/locore.S new file mode 100644 index 0000000..8e38d40 --- /dev/null +++ b/sys/ia64/ia64/locore.S @@ -0,0 +1,394 @@ +/*- + * 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$ + */ +/* + * 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/cdefs.h> +#include <machine/asm.h> +#include <machine/fpu.h> +#include <sys/syscall.h> +#include <assym.s> + +#ifndef EVCNT_COUNTERS +#define _LOCORE +#include <machine/intrcnt.h> +#endif + +/* + * Perform actions necessary to switch to a new context. The + * hwpcb should be in a0. + */ +#define SWITCH_CONTEXT \ + /* Make a note of the context we're running on. */ \ + stq a0, curpcb ; \ + \ + /* Swap in the new context. */ \ + call_pal PAL_OSF1_swpctx + + .text + +/* + * Not really a leaf but we can't return. + */ +LEAF(locorestart, 1) + + movl r8=ia64_vector_table /* set up IVT early */ + movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 /* and VHPT */ + ;; + mov cr.iva=r8 + mov cr.pta=r9 + ;; + srlz.i + ;; + srlz.d + ;; + movl gp=__gp /* find kernel globals */ + ;; + br.call.sptk.many rp=ia64_init + + /* XXX switch to proc0 here */ + movl r16=proc0 + ;; + add r16=P_ADDR,r16 + ;; + ld8 r16=[r16] + ;; + add r17=SIZEOF_USER,r16 /* address of backing store */ + add r18=U_PCB_SP,r16 /* stack pointer */ + ;; + ld8 r18=[r18] + mov ar.rsc=0 + cover + ;; + flushrs + ;; + mov ar.bspstore=r17 + mov sp=r18 + ;; + loadrs + mov ar.rsc=3 + ;; + alloc r16=ar.pfs,0,0,0,0 + ;; + br.call.sptk.many rp=mi_startup + + /* NOTREACHED */ + +#if 0 + /* Load KGP with current GP. */ + or a0,zero,s0 /* save pfn */ + or gp,zero,a0 + call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */ + or s0,zero,a0 /* restore pfn */ + + /* + * Call alpha_init() to do pre-main initialization. + * alpha_init() gets the arguments we were called with, + * which are already in a0, a1, a2, a3, and a4. + */ + CALL(alpha_init) + + /* Set up the virtual page table pointer. */ + ldiq a0, VPTBASE + call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */ + + /* + * Switch to proc0's PCB, which is at U_PCB off of proc0paddr. + */ + lda t0,proc0 /* get phys addr of pcb */ + ldq a0,P_MD_PCBPADDR(t0) + SWITCH_CONTEXT + + /* + * We've switched to a new page table base, so invalidate the TLB + * and I-stream. This happens automatically everywhere but here. + */ + ldiq a0, -2 /* TBIA */ + call_pal PAL_OSF1_tbi + call_pal PAL_imb + + /* + * Construct a fake trap frame, so execve() can work normally. + * Note that setregs() is responsible for setting its contents + * to 'reasonable' values. + */ + lda sp,-(FRAME_SIZE * 8)(sp) /* space for struct trapframe */ + mov sp, a0 /* arg is frame ptr */ + CALL(mi_startup) /* go to mi_startup()! */ + + /* + * Call exception_return, to simulate return from (fake) + * exception to user-land, running process 1, init! + */ + jmp zero, exception_return /* "And that's all she wrote." */ + +#endif + END(locorestart) + + +/**************************************************************************/ + +/* + * Signal "trampoline" code. Invoked from RTE setup by sendsig(). + * + * On entry, registers look like: + * + * r14 signal number + * r15 pointer to siginfo_t + * r16 pointer to signal context frame (scp) + * r17 address of handler function descriptor + * r18 address of new backing store (if any) + * sp pointer to sigframe + */ + +LEAF(sigcode,0) + ld8 r8=[r17],8 /* function address */ + ;; + ld8 gp=[r17] /* function's gp value */ + mov b6=r8 /* transfer to a branch register */ + cover + ;; + alloc r5=ar.pfs,0,0,3,0 /* register frame for call */ + ;; + mov out0=r14 /* signal number */ + add r8=UC_MCONTEXT_MC_AR_BSP,r16 /* address or mc_ar_bsp */ + mov r9=ar.bsp /* save ar.bsp */ + ;; + st8 [r8]=r9 + cmp.eq p1,p0=r0,r18 /* check for new bs */ +(p1) br.cond.sptk.few 1f /* branch if not switching */ + flushrs /* flush out to old bs */ + mov ar.rsc=0 /* switch off RSE */ + add r8=UC_MCONTEXT_MC_AR_RNAT,r16 /* address of mc_ar_rnat */ + ;; + mov r9=ar.rnat /* value of ar.rnat after flush */ + mov ar.bspstore=r18 /* point at new bs */ + ;; + st8 [r8]=r9 /* remember ar.rnat */ + mov ar.rsc=15 /* XXX bogus value - check */ + invala + ;; +1: mov out1=r15 /* siginfo */ + mov out2=r16 /* ucontext */ + mov r4=r17 /* save ucontext pointer from call */ + br.call.sptk.few rp=b6 /* call the signal handler */ +(p1) br.cond.sptk.few 2f /* note: p1 is preserved */ + flushrs + mov ar.rsc=0 + add r8=UC_MCONTEXT_MC_AR_RNAT,r4 /* address of mc_ar_rnat */ + ;; + ld8 r9=[r8] + ;; + add r8=UC_MCONTEXT_MC_AR_BSP,r4 /* address of mc_ar_bsp */ + ;; + ld8 r10=[r8] + ;; + mov ar.bspstore=r10 + ;; + mov ar.rnat=r9 + mov ar.rsc=15 +2: + CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */ + mov out0=ret0 /* if that failed, get error code */ + CALLSYS_NOERROR(exit) /* and call exit() with it. */ +XLEAF(esigcode) + END(sigcode) + + .data + EXPORT(szsigcode) + .quad esigcode-sigcode + .text + +/**************************************************************************/ + +/* + * savefpstate: Save a process's floating point state. + * + * Arguments: + * a0 'struct fpstate *' to save into + */ + +LEAF(savefpstate, 1) +#if 0 + LDGP(pv) + /* save all of the FP registers */ + lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ + stt $f0, (0 * 8)(t1) /* save first register, using hw name */ + stt $f1, (1 * 8)(t1) /* etc. */ + stt $f2, (2 * 8)(t1) + stt $f3, (3 * 8)(t1) + stt $f4, (4 * 8)(t1) + stt $f5, (5 * 8)(t1) + stt $f6, (6 * 8)(t1) + stt $f7, (7 * 8)(t1) + stt $f8, (8 * 8)(t1) + stt $f9, (9 * 8)(t1) + stt $f10, (10 * 8)(t1) + stt $f11, (11 * 8)(t1) + stt $f12, (12 * 8)(t1) + stt $f13, (13 * 8)(t1) + stt $f14, (14 * 8)(t1) + stt $f15, (15 * 8)(t1) + stt $f16, (16 * 8)(t1) + stt $f17, (17 * 8)(t1) + stt $f18, (18 * 8)(t1) + stt $f19, (19 * 8)(t1) + stt $f20, (20 * 8)(t1) + stt $f21, (21 * 8)(t1) + stt $f22, (22 * 8)(t1) + stt $f23, (23 * 8)(t1) + stt $f24, (24 * 8)(t1) + stt $f25, (25 * 8)(t1) + stt $f26, (26 * 8)(t1) + stt $f27, (27 * 8)(t1) + stt $f28, (28 * 8)(t1) + stt $f29, (29 * 8)(t1) + stt $f30, (30 * 8)(t1) + + /* + * Then save the FPCR; note that the necessary 'trapb's are taken + * care of on kernel entry and exit. + */ + mf_fpcr ft0 + stt ft0, FPREG_FPR_CR(a0) /* store to FPCR save area */ + + RET +#endif + END(savefpstate) + +/**************************************************************************/ + +/* + * restorefpstate: Restore a process's floating point state. + * + * Arguments: + * a0 'struct fpstate *' to restore from + */ + +LEAF(restorefpstate, 1) +#if 0 + LDGP(pv) + /* + * Restore the FPCR; note that the necessary 'trapb's are taken care of + * on kernel entry and exit. + */ + ldt ft0, FPREG_FPR_CR(a0) /* load from FPCR save area */ + mt_fpcr ft0 + + /* Restore all of the FP registers. */ + lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ + ldt $f0, (0 * 8)(t1) /* restore first reg., using hw name */ + ldt $f1, (1 * 8)(t1) /* etc. */ + ldt $f2, (2 * 8)(t1) + ldt $f3, (3 * 8)(t1) + ldt $f4, (4 * 8)(t1) + ldt $f5, (5 * 8)(t1) + ldt $f6, (6 * 8)(t1) + ldt $f7, (7 * 8)(t1) + ldt $f8, (8 * 8)(t1) + ldt $f9, (9 * 8)(t1) + ldt $f10, (10 * 8)(t1) + ldt $f11, (11 * 8)(t1) + ldt $f12, (12 * 8)(t1) + ldt $f13, (13 * 8)(t1) + ldt $f14, (14 * 8)(t1) + ldt $f15, (15 * 8)(t1) + ldt $f16, (16 * 8)(t1) + ldt $f17, (17 * 8)(t1) + ldt $f18, (18 * 8)(t1) + ldt $f19, (19 * 8)(t1) + ldt $f20, (20 * 8)(t1) + ldt $f21, (21 * 8)(t1) + ldt $f22, (22 * 8)(t1) + ldt $f23, (23 * 8)(t1) + ldt $f24, (24 * 8)(t1) + ldt $f25, (25 * 8)(t1) + ldt $f26, (26 * 8)(t1) + ldt $f27, (27 * 8)(t1) + ldt $f28, (28 * 8)(t1) + ldt $f29, (29 * 8)(t1) + ldt $f30, (30 * 8)(t1) + + RET +#endif + END(restorefpstate) + +/* + * When starting init, call this to configure the process for user + * mode. This will be inherited by other processes. + */ + LEAF_NOPROFILE(prepare_usermode, 0) + END(prepare_usermode) + + .data + EXPORT(proc0paddr) + .quad 0 + + .text + +/* XXX: make systat/vmstat happy */ + .data +EXPORT(intrnames) + .asciz "clock" +intr_n = 0 +.rept INTRCNT_COUNT + .ascii "intr " + .byte intr_n / 10 + '0, intr_n % 10 + '0 + .asciz " " /* space for platform-specific rewrite */ + intr_n = intr_n + 1 +.endr +EXPORT(eintrnames) + .align 8 +EXPORT(intrcnt) + .fill INTRCNT_COUNT + 1, 8, 0 +EXPORT(eintrcnt) + .text diff --git a/sys/ia64/ia64/locore.s b/sys/ia64/ia64/locore.s new file mode 100644 index 0000000..8e38d40 --- /dev/null +++ b/sys/ia64/ia64/locore.s @@ -0,0 +1,394 @@ +/*- + * 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$ + */ +/* + * 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/cdefs.h> +#include <machine/asm.h> +#include <machine/fpu.h> +#include <sys/syscall.h> +#include <assym.s> + +#ifndef EVCNT_COUNTERS +#define _LOCORE +#include <machine/intrcnt.h> +#endif + +/* + * Perform actions necessary to switch to a new context. The + * hwpcb should be in a0. + */ +#define SWITCH_CONTEXT \ + /* Make a note of the context we're running on. */ \ + stq a0, curpcb ; \ + \ + /* Swap in the new context. */ \ + call_pal PAL_OSF1_swpctx + + .text + +/* + * Not really a leaf but we can't return. + */ +LEAF(locorestart, 1) + + movl r8=ia64_vector_table /* set up IVT early */ + movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 /* and VHPT */ + ;; + mov cr.iva=r8 + mov cr.pta=r9 + ;; + srlz.i + ;; + srlz.d + ;; + movl gp=__gp /* find kernel globals */ + ;; + br.call.sptk.many rp=ia64_init + + /* XXX switch to proc0 here */ + movl r16=proc0 + ;; + add r16=P_ADDR,r16 + ;; + ld8 r16=[r16] + ;; + add r17=SIZEOF_USER,r16 /* address of backing store */ + add r18=U_PCB_SP,r16 /* stack pointer */ + ;; + ld8 r18=[r18] + mov ar.rsc=0 + cover + ;; + flushrs + ;; + mov ar.bspstore=r17 + mov sp=r18 + ;; + loadrs + mov ar.rsc=3 + ;; + alloc r16=ar.pfs,0,0,0,0 + ;; + br.call.sptk.many rp=mi_startup + + /* NOTREACHED */ + +#if 0 + /* Load KGP with current GP. */ + or a0,zero,s0 /* save pfn */ + or gp,zero,a0 + call_pal PAL_OSF1_wrkgp /* clobbers a0, t0, t8-t11 */ + or s0,zero,a0 /* restore pfn */ + + /* + * Call alpha_init() to do pre-main initialization. + * alpha_init() gets the arguments we were called with, + * which are already in a0, a1, a2, a3, and a4. + */ + CALL(alpha_init) + + /* Set up the virtual page table pointer. */ + ldiq a0, VPTBASE + call_pal PAL_OSF1_wrvptptr /* clobbers a0, t0, t8-t11 */ + + /* + * Switch to proc0's PCB, which is at U_PCB off of proc0paddr. + */ + lda t0,proc0 /* get phys addr of pcb */ + ldq a0,P_MD_PCBPADDR(t0) + SWITCH_CONTEXT + + /* + * We've switched to a new page table base, so invalidate the TLB + * and I-stream. This happens automatically everywhere but here. + */ + ldiq a0, -2 /* TBIA */ + call_pal PAL_OSF1_tbi + call_pal PAL_imb + + /* + * Construct a fake trap frame, so execve() can work normally. + * Note that setregs() is responsible for setting its contents + * to 'reasonable' values. + */ + lda sp,-(FRAME_SIZE * 8)(sp) /* space for struct trapframe */ + mov sp, a0 /* arg is frame ptr */ + CALL(mi_startup) /* go to mi_startup()! */ + + /* + * Call exception_return, to simulate return from (fake) + * exception to user-land, running process 1, init! + */ + jmp zero, exception_return /* "And that's all she wrote." */ + +#endif + END(locorestart) + + +/**************************************************************************/ + +/* + * Signal "trampoline" code. Invoked from RTE setup by sendsig(). + * + * On entry, registers look like: + * + * r14 signal number + * r15 pointer to siginfo_t + * r16 pointer to signal context frame (scp) + * r17 address of handler function descriptor + * r18 address of new backing store (if any) + * sp pointer to sigframe + */ + +LEAF(sigcode,0) + ld8 r8=[r17],8 /* function address */ + ;; + ld8 gp=[r17] /* function's gp value */ + mov b6=r8 /* transfer to a branch register */ + cover + ;; + alloc r5=ar.pfs,0,0,3,0 /* register frame for call */ + ;; + mov out0=r14 /* signal number */ + add r8=UC_MCONTEXT_MC_AR_BSP,r16 /* address or mc_ar_bsp */ + mov r9=ar.bsp /* save ar.bsp */ + ;; + st8 [r8]=r9 + cmp.eq p1,p0=r0,r18 /* check for new bs */ +(p1) br.cond.sptk.few 1f /* branch if not switching */ + flushrs /* flush out to old bs */ + mov ar.rsc=0 /* switch off RSE */ + add r8=UC_MCONTEXT_MC_AR_RNAT,r16 /* address of mc_ar_rnat */ + ;; + mov r9=ar.rnat /* value of ar.rnat after flush */ + mov ar.bspstore=r18 /* point at new bs */ + ;; + st8 [r8]=r9 /* remember ar.rnat */ + mov ar.rsc=15 /* XXX bogus value - check */ + invala + ;; +1: mov out1=r15 /* siginfo */ + mov out2=r16 /* ucontext */ + mov r4=r17 /* save ucontext pointer from call */ + br.call.sptk.few rp=b6 /* call the signal handler */ +(p1) br.cond.sptk.few 2f /* note: p1 is preserved */ + flushrs + mov ar.rsc=0 + add r8=UC_MCONTEXT_MC_AR_RNAT,r4 /* address of mc_ar_rnat */ + ;; + ld8 r9=[r8] + ;; + add r8=UC_MCONTEXT_MC_AR_BSP,r4 /* address of mc_ar_bsp */ + ;; + ld8 r10=[r8] + ;; + mov ar.bspstore=r10 + ;; + mov ar.rnat=r9 + mov ar.rsc=15 +2: + CALLSYS_NOERROR(sigreturn) /* and call sigreturn() with it. */ + mov out0=ret0 /* if that failed, get error code */ + CALLSYS_NOERROR(exit) /* and call exit() with it. */ +XLEAF(esigcode) + END(sigcode) + + .data + EXPORT(szsigcode) + .quad esigcode-sigcode + .text + +/**************************************************************************/ + +/* + * savefpstate: Save a process's floating point state. + * + * Arguments: + * a0 'struct fpstate *' to save into + */ + +LEAF(savefpstate, 1) +#if 0 + LDGP(pv) + /* save all of the FP registers */ + lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ + stt $f0, (0 * 8)(t1) /* save first register, using hw name */ + stt $f1, (1 * 8)(t1) /* etc. */ + stt $f2, (2 * 8)(t1) + stt $f3, (3 * 8)(t1) + stt $f4, (4 * 8)(t1) + stt $f5, (5 * 8)(t1) + stt $f6, (6 * 8)(t1) + stt $f7, (7 * 8)(t1) + stt $f8, (8 * 8)(t1) + stt $f9, (9 * 8)(t1) + stt $f10, (10 * 8)(t1) + stt $f11, (11 * 8)(t1) + stt $f12, (12 * 8)(t1) + stt $f13, (13 * 8)(t1) + stt $f14, (14 * 8)(t1) + stt $f15, (15 * 8)(t1) + stt $f16, (16 * 8)(t1) + stt $f17, (17 * 8)(t1) + stt $f18, (18 * 8)(t1) + stt $f19, (19 * 8)(t1) + stt $f20, (20 * 8)(t1) + stt $f21, (21 * 8)(t1) + stt $f22, (22 * 8)(t1) + stt $f23, (23 * 8)(t1) + stt $f24, (24 * 8)(t1) + stt $f25, (25 * 8)(t1) + stt $f26, (26 * 8)(t1) + stt $f27, (27 * 8)(t1) + stt $f28, (28 * 8)(t1) + stt $f29, (29 * 8)(t1) + stt $f30, (30 * 8)(t1) + + /* + * Then save the FPCR; note that the necessary 'trapb's are taken + * care of on kernel entry and exit. + */ + mf_fpcr ft0 + stt ft0, FPREG_FPR_CR(a0) /* store to FPCR save area */ + + RET +#endif + END(savefpstate) + +/**************************************************************************/ + +/* + * restorefpstate: Restore a process's floating point state. + * + * Arguments: + * a0 'struct fpstate *' to restore from + */ + +LEAF(restorefpstate, 1) +#if 0 + LDGP(pv) + /* + * Restore the FPCR; note that the necessary 'trapb's are taken care of + * on kernel entry and exit. + */ + ldt ft0, FPREG_FPR_CR(a0) /* load from FPCR save area */ + mt_fpcr ft0 + + /* Restore all of the FP registers. */ + lda t1, FPREG_FPR_REGS(a0) /* get address of FP reg. save area */ + ldt $f0, (0 * 8)(t1) /* restore first reg., using hw name */ + ldt $f1, (1 * 8)(t1) /* etc. */ + ldt $f2, (2 * 8)(t1) + ldt $f3, (3 * 8)(t1) + ldt $f4, (4 * 8)(t1) + ldt $f5, (5 * 8)(t1) + ldt $f6, (6 * 8)(t1) + ldt $f7, (7 * 8)(t1) + ldt $f8, (8 * 8)(t1) + ldt $f9, (9 * 8)(t1) + ldt $f10, (10 * 8)(t1) + ldt $f11, (11 * 8)(t1) + ldt $f12, (12 * 8)(t1) + ldt $f13, (13 * 8)(t1) + ldt $f14, (14 * 8)(t1) + ldt $f15, (15 * 8)(t1) + ldt $f16, (16 * 8)(t1) + ldt $f17, (17 * 8)(t1) + ldt $f18, (18 * 8)(t1) + ldt $f19, (19 * 8)(t1) + ldt $f20, (20 * 8)(t1) + ldt $f21, (21 * 8)(t1) + ldt $f22, (22 * 8)(t1) + ldt $f23, (23 * 8)(t1) + ldt $f24, (24 * 8)(t1) + ldt $f25, (25 * 8)(t1) + ldt $f26, (26 * 8)(t1) + ldt $f27, (27 * 8)(t1) + ldt $f28, (28 * 8)(t1) + ldt $f29, (29 * 8)(t1) + ldt $f30, (30 * 8)(t1) + + RET +#endif + END(restorefpstate) + +/* + * When starting init, call this to configure the process for user + * mode. This will be inherited by other processes. + */ + LEAF_NOPROFILE(prepare_usermode, 0) + END(prepare_usermode) + + .data + EXPORT(proc0paddr) + .quad 0 + + .text + +/* XXX: make systat/vmstat happy */ + .data +EXPORT(intrnames) + .asciz "clock" +intr_n = 0 +.rept INTRCNT_COUNT + .ascii "intr " + .byte intr_n / 10 + '0, intr_n % 10 + '0 + .asciz " " /* space for platform-specific rewrite */ + intr_n = intr_n + 1 +.endr +EXPORT(eintrnames) + .align 8 +EXPORT(intrcnt) + .fill INTRCNT_COUNT + 1, 8, 0 +EXPORT(eintrcnt) + .text diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c new file mode 100644 index 0000000..051f941 --- /dev/null +++ b/sys/ia64/ia64/machdep.c @@ -0,0 +1,1364 @@ +/*- + * 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 "opt_compat.h" +#include "opt_ddb.h" +#include "opt_simos.h" +#include "opt_msgbuf.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/eventhandler.h> +#include <sys/sysproto.h> +#include <sys/signalvar.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/reboot.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/mbuf.h> +#include <sys/vmmeter.h> +#include <sys/msgbuf.h> +#include <sys/exec.h> +#include <sys/sysctl.h> +#include <sys/uio.h> +#include <sys/linker.h> +#include <sys/random.h> +#include <net/netisr.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> +#include <vm/vm_object.h> +#include <vm/vm_pager.h> +#include <sys/user.h> +#include <sys/ptrace.h> +#include <machine/clock.h> +#include <machine/md_var.h> +#include <machine/reg.h> +#include <machine/fpu.h> +#include <machine/pal.h> +#include <machine/efi.h> +#include <machine/bootinfo.h> +#include <machine/mutex.h> +#include <machine/vmparam.h> +#include <machine/elf.h> +#include <ddb/ddb.h> +#include <alpha/alpha/db_instruction.h> +#include <sys/vnode.h> +#include <miscfs/procfs/procfs.h> +#include <machine/sigframe.h> + +u_int64_t cycles_per_usec; +u_int32_t cycles_per_sec; +int cold = 1; +struct bootinfo_kernel bootinfo; + +struct cpuhead cpuhead; + +struct mtx sched_lock; +struct mtx Giant; + +struct user *proc0paddr; + +char machine[] = "ia64"; +SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); + +static char cpu_model[128]; +SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); + +#ifdef DDB +/* start and end of kernel symbol table */ +void *ksym_start, *ksym_end; +#endif + +int ia64_unaligned_print = 1; /* warn about unaligned accesses */ +int ia64_unaligned_fix = 1; /* fix up unaligned accesses */ +int ia64_unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ + +SYSCTL_INT(_machdep, CPU_UNALIGNED_PRINT, unaligned_print, + CTLFLAG_RW, &ia64_unaligned_print, 0, ""); + +SYSCTL_INT(_machdep, CPU_UNALIGNED_FIX, unaligned_fix, + CTLFLAG_RW, &ia64_unaligned_fix, 0, ""); + +SYSCTL_INT(_machdep, CPU_UNALIGNED_SIGBUS, unaligned_sigbus, + CTLFLAG_RW, &ia64_unaligned_sigbus, 0, ""); + +static void cpu_startup __P((void *)); +SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) + +static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf"); + +struct msgbuf *msgbufp=0; + +int bootverbose = 0, Maxmem = 0; +long dumplo; + +int totalphysmem; /* total amount of physical memory in system */ +int physmem; /* physical memory used by NetBSD + some rsvd */ +int resvmem; /* amount of memory reserved for PROM */ +int unusedmem; /* amount of memory for OS that we don't use */ +int unknownmem; /* amount of memory with an unknown use */ +int ncpus; /* number of cpus */ + +vm_offset_t phys_avail[10]; + +static int +sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) +{ + int error = sysctl_handle_int(oidp, 0, ia64_ptob(physmem), req); + return (error); +} + +SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, + 0, 0, sysctl_hw_physmem, "I", ""); + +static int +sysctl_hw_usermem(SYSCTL_HANDLER_ARGS) +{ + int error = sysctl_handle_int(oidp, 0, + ia64_ptob(physmem - cnt.v_wire_count), req); + return (error); +} + +SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD, + 0, 0, sysctl_hw_usermem, "I", ""); + +SYSCTL_INT(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, ""); + +/* must be 2 less so 0 0 can signal end of chunks */ +#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) + +static void identifycpu __P((void)); + +static vm_offset_t buffer_sva, buffer_eva; +vm_offset_t clean_sva, clean_eva; +static vm_offset_t pager_sva, pager_eva; + +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) + +static void +cpu_startup(dummy) + void *dummy; +{ + unsigned int i; + caddr_t v; + vm_offset_t maxaddr; + vm_size_t size = 0; + vm_offset_t firstaddr; + vm_offset_t minaddr; + + if (boothowto & RB_VERBOSE) + bootverbose++; + + /* + * Good {morning,afternoon,evening,night}. + */ + printf("%s", version); + identifycpu(); + + /* startrtclock(); */ +#ifdef PERFMON + perfmon_init(); +#endif + printf("real memory = %ld (%ldK bytes)\n", ia64_ptob(Maxmem), ia64_ptob(Maxmem) / 1024); + + /* + * 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%08lx - 0x%08lx, %d bytes (%d pages)\n", phys_avail[indx], + phys_avail[indx + 1] - 1, size1, size1 / PAGE_SIZE); + } + } + + /* + * Calculate callout wheel size + */ + for (callwheelsize = 1, callwheelbits = 0; + callwheelsize < ncallout; + callwheelsize <<= 1, ++callwheelbits) + ; + callwheelmask = callwheelsize - 1; + + /* + * Allocate space for system data structures. + * The first available kernel virtual address is in "v". + * As pages of kernel virtual memory are allocated, "v" is incremented. + * As pages of memory are allocated and cleared, + * "firstaddr" is incremented. + * An index into the kernel page table corresponding to the + * virtual memory address maintained in "v" is kept in "mapaddr". + */ + + /* + * Make two passes. The first pass calculates how much memory is + * needed and allocates it. The second pass assigns virtual + * addresses to the various data structures. + */ + firstaddr = 0; +again: + v = (caddr_t)firstaddr; + +#define valloc(name, type, num) \ + (name) = (type *)v; v = (caddr_t)((name)+(num)) +#define valloclim(name, type, num, lim) \ + (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) + + valloc(callout, struct callout, ncallout); + valloc(callwheel, struct callout_tailq, callwheelsize); + + /* + * The nominal buffer size (and minimum KVA allocation) is BKVASIZE. + * For the first 64MB of ram nominally allocate sufficient buffers to + * cover 1/4 of our ram. Beyond the first 64MB allocate additional + * buffers to cover 1/20 of our ram over 64MB. + */ + + if (nbuf == 0) { + int factor = 4 * BKVASIZE / PAGE_SIZE; + + nbuf = 50; + if (physmem > 1024) + nbuf += min((physmem - 1024) / factor, 16384 / factor); + if (physmem > 16384) + nbuf += (physmem - 16384) * 2 / (factor * 5); + } + nswbuf = max(min(nbuf/4, 64), 16); + + valloc(swbuf, struct buf, nswbuf); + valloc(buf, struct buf, nbuf); + v = bufhashinit(v); + + /* + * End of first pass, size has been calculated so allocate memory + */ + if (firstaddr == 0) { + size = (vm_size_t)(v - firstaddr); + firstaddr = (vm_offset_t)kmem_alloc(kernel_map, round_page(size)); + if (firstaddr == 0) + panic("startup: no room for tables"); + goto again; + } + + /* + * End of second pass, addresses have been assigned + */ + if ((vm_size_t)(v - firstaddr) != size) + panic("startup: table size inconsistency"); + + clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, + (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size); + buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, + (nbuf*BKVASIZE)); + pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, + (nswbuf*MAXPHYS) + pager_map_size); + pager_map->system_map = 1; + exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, + (16*(ARG_MAX+(PAGE_SIZE*3)))); + + /* + * Finally, allocate mbuf pool. Since mclrefcnt is an off-size + * we use the more space efficient malloc in place of kmem_alloc. + */ + { + vm_offset_t mb_map_size; + + mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES + + (nmbclusters + nmbufs / 4) * sizeof(union mext_refcnt); + mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE)); + mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, + &maxaddr, mb_map_size); + mb_map->system_map = 1; + } + + /* + * Initialize callouts + */ + SLIST_INIT(&callfree); + for (i = 0; i < ncallout; i++) { + callout_init(&callout[i]); + callout[i].c_flags = CALLOUT_LOCAL_ALLOC; + SLIST_INSERT_HEAD(&callfree, &callout[i], c_links.sle); + } + + for (i = 0; i < callwheelsize; i++) { + TAILQ_INIT(&callwheel[i]); + } + +#if defined(USERCONFIG) +#if defined(USERCONFIG_BOOT) + if (1) +#else + if (boothowto & RB_CONFIG) +#endif + { + userconfig(); + cninit(); /* the preferred console may have changed */ + } +#endif + + printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), + ptoa(cnt.v_free_count) / 1024); + + /* + * Set up buffers, so they can be used to read disk labels. + */ + bufinit(); + vm_pager_bufferinit(); +} + +int +register_netisr(num, handler) + int num; + netisr_t *handler; +{ + + if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { + printf("register_netisr: bad isr number: %d\n", num); + return (EINVAL); + } + netisrs[num] = handler; + return (0); +} + +int +unregister_netisr(num) + int num; +{ + + if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { + printf("unregister_netisr: bad isr number: %d\n", num); + return (EINVAL); + } + netisrs[num] = NULL; + return (0); +} + +static void +identifycpu(void) +{ + /* print cpu type & version */ +} + +extern char kernel_text[], _end[]; + +#define DEBUG_MD + +void +ia64_init() +{ + int phys_avail_cnt; + vm_offset_t kernstart, kernend; + vm_offset_t kernstartpfn, kernendpfn, pfn0, pfn1; + char *p; + struct efi_memory_descriptor ski_md[2]; /* XXX */ + struct efi_memory_descriptor *mdp; + int mdcount, i; + + /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ + + /* + * TODO: Disable interrupts, floating point etc. + * Maybe flush cache and tlb + */ + __asm __volatile("mov ar.fpsr=%0" :: "r"(IA64_FPSR_DEFAULT)); + + /* + * TODO: Get critical system information (if possible, from the + * information provided by the boot program). + */ + + /* + * Initalize the (temporary) bootstrap console interface, so + * we can use printf until the VM system starts being setup. + * The real console is initialized before then. + * TODO: I guess we start with a serial console here. + */ + ssccnattach(); + + /* OUTPUT NOW ALLOWED */ + + /* + * Find the beginning and end of the kernel. + */ + kernstart = trunc_page(kernel_text); +#ifdef DDB + ksym_start = (void *)bootinfo.ssym; + ksym_end = (void *)bootinfo.esym; + kernend = (vm_offset_t)round_page(ksym_end); +#else + kernend = (vm_offset_t)round_page(_end); +#endif + /* But if the bootstrap tells us otherwise, believe it! */ + if (bootinfo.kernend) + kernend = round_page(bootinfo.kernend); + preload_metadata = (caddr_t)bootinfo.modptr; + kern_envp = bootinfo.envp; + + p = getenv("kernelname"); + if (p) + strncpy(kernelname, p, sizeof(kernelname) - 1); + + kernstartpfn = atop(IA64_RR_MASK(kernstart)); + kernendpfn = atop(IA64_RR_MASK(kernend)); + + /* + * Size the memory regions and load phys_avail[] with the results. + */ + + /* + * XXX hack for ski. In reality, the loader will probably ask + * EFI and pass the results to us. Possibly, we will call EFI + * directly. + */ + ski_md[0].emd_type = EFI_CONVENTIONAL_MEMORY; + ski_md[0].emd_physical_start = 2L*1024*1024; + ski_md[0].emd_virtul_start = 0; + ski_md[0].emd_number_of_pages = (64L*1024*1024)>>12; + ski_md[0].emd_attribute = EFI_MEMORY_WB; + + ski_md[1].emd_type = EFI_CONVENTIONAL_MEMORY; + ski_md[1].emd_physical_start = 4096L*1024*1024; + ski_md[1].emd_virtul_start = 0; + ski_md[1].emd_number_of_pages = (32L*1024*1024)>>12; + ski_md[1].emd_attribute = EFI_MEMORY_WB; + + mdcount = 1; /* ignore the high memory for now */ + + /* + * Find out how much memory is available, by looking at + * the memory descriptors. + */ +#ifdef DEBUG_MD + printf("Memory descriptor count: %d\n", mdcount); +#endif + + phys_avail_cnt = 0; + for (i = 0; i < mdcount; i++) { + mdp = &ski_md[i]; +#ifdef DEBUG_MD + printf("MD %d: type %d pa 0x%lx cnt 0x%lx\n", i, + mdp->emd_type, + mdp->emd_physical_start, + mdp->emd_number_of_pages); +#endif + totalphysmem += mdp->emd_number_of_pages; + + if (mdp->emd_type != EFI_CONVENTIONAL_MEMORY) { + resvmem += mdp->emd_number_of_pages; + continue; + } + + /* + * We have a memory descriptors available for system + * software use. We must determine if this cluster + * holds the kernel. + */ + physmem += mdp->emd_number_of_pages; + pfn0 = atop(mdp->emd_physical_start); + pfn1 = pfn0 + mdp->emd_number_of_pages; + if (pfn0 <= kernendpfn && kernstartpfn <= pfn1) { + /* + * Must compute the location of the kernel + * within the segment. + */ +#ifdef DEBUG_MD + printf("Descriptor %d contains kernel\n", i); +#endif + if (pfn0 < kernstartpfn) { + /* + * There is a chunk before the kernel. + */ +#ifdef DEBUG_MD + printf("Loading chunk before kernel: " + "0x%lx / 0x%lx\n", pfn0, kernstartpfn); +#endif + phys_avail[phys_avail_cnt] = ia64_ptob(pfn0); + phys_avail[phys_avail_cnt+1] = ia64_ptob(kernstartpfn); + phys_avail_cnt += 2; + } + if (kernendpfn < pfn1) { + /* + * There is a chunk after the kernel. + */ +#ifdef DEBUG_MD + printf("Loading chunk after kernel: " + "0x%lx / 0x%lx\n", kernendpfn, pfn1); +#endif + phys_avail[phys_avail_cnt] = ia64_ptob(kernendpfn); + phys_avail[phys_avail_cnt+1] = ia64_ptob(pfn1); + phys_avail_cnt += 2; + } + } else { + /* + * Just load this cluster as one chunk. + */ +#ifdef DEBUG_MD + printf("Loading descriptor %d: 0x%lx / 0x%lx\n", i, + pfn0, pfn1); +#endif + phys_avail[phys_avail_cnt] = ia64_ptob(pfn0); + phys_avail[phys_avail_cnt+1] = ia64_ptob(pfn1); + phys_avail_cnt += 2; + + } + } + phys_avail[phys_avail_cnt] = 0; + + Maxmem = physmem; + + /* + * Initialize error message buffer (at end of core). + */ + { + size_t sz = round_page(MSGBUF_SIZE); + int i = phys_avail_cnt - 2; + + /* shrink so that it'll fit in the last segment */ + if (phys_avail[i+1] - phys_avail[i] < sz) + sz = phys_avail[i+1] - phys_avail[i]; + + phys_avail[i+1] -= sz; + msgbufp = (struct msgbuf*) IA64_PHYS_TO_RR7(phys_avail[i+1]); + + msgbufinit(msgbufp, sz); + + /* Remove the last segment if it now has no pages. */ + if (phys_avail[i] == phys_avail[i+1]) + phys_avail[i] = 0; + + /* warn if the message buffer had to be shrunk */ + if (sz != round_page(MSGBUF_SIZE)) + printf("WARNING: %ld bytes not available for msgbuf in last cluster (%ld used)\n", + round_page(MSGBUF_SIZE), sz); + + } + + /* + * Init mapping for u page(s) for proc 0 + */ + proc0.p_addr = proc0paddr = + (struct user *)pmap_steal_memory(UPAGES * PAGE_SIZE); + + /* + * Setup the global data for the bootstrap cpu. + */ + { + size_t sz = round_page(UPAGES * PAGE_SIZE); + globalp = (struct globaldata *) pmap_steal_memory(sz); + globaldata_init(globalp, 0, sz); + PCPU_GET(next_asn) = 1; /* 0 used for proc0 pmap */ + } + + /* + * Initialize the virtual memory system, and set the + * page table base register in proc 0's PCB. + */ + pmap_bootstrap(); + + /* + * Initialize the rest of proc 0's PCB, and cache its physical + * address. + */ + proc0.p_md.md_pcbpaddr = + (struct pcb *)IA64_RR_MASK((vm_offset_t)&proc0paddr->u_pcb); + + /* + * Set the kernel sp, reserving space for an (empty) trapframe, + * and make proc0's trapframe pointer point to it for sanity. + */ + proc0paddr->u_pcb.pcb_sp = + (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe); + proc0.p_md.md_tf = + (struct trapframe *)proc0paddr->u_pcb.pcb_sp; + PCPU_SET(curproc, &proc0); + + /* + * Record all cpus in a list. + */ + SLIST_INIT(&cpuhead); + SLIST_INSERT_HEAD(&cpuhead, GLOBALP, gd_allcpu); + + /* + * Initialise mutexes. + */ + mtx_init(&Giant, "Giant", MTX_DEF); + mtx_init(&sched_lock, "sched lock", MTX_SPIN); + +#if 0 + /* + * Enable interrupts on first release (in switch_trampoline). + */ + sched_lock.mtx_saveipl = ALPHA_PSL_IPL_0; +#endif + + /* + * Look at arguments passed to us and compute boothowto. + */ + boothowto = 0; +#ifdef KADB + boothowto |= RB_KDB; +#endif +/* boothowto |= RB_KDB | RB_GDB; */ + for (p = bootinfo.boot_flags; p && *p != '\0'; p++) { + /* + * Note that we'd really like to differentiate case here, + * but the Ia64 AXP Architecture Reference Manual + * says that we shouldn't. + */ + switch (*p) { + case 'a': /* autoboot */ + case 'A': + boothowto &= ~RB_SINGLE; + break; + +#ifdef DEBUG + case 'c': /* crash dump immediately after autoconfig */ + case 'C': + boothowto |= RB_DUMP; + break; +#endif + +#if defined(DDB) + case 'd': /* break into the kernel debugger ASAP */ + case 'D': + boothowto |= RB_KDB; + break; + case 'g': /* use kernel gdb */ + case 'G': + boothowto |= RB_GDB; + break; +#endif + + case 'h': /* always halt, never reboot */ + case 'H': + boothowto |= RB_HALT; + break; + +#if 0 + case 'm': /* mini root present in memory */ + case 'M': + boothowto |= RB_MINIROOT; + break; +#endif + + case 'n': /* askname */ + case 'N': + boothowto |= RB_ASKNAME; + break; + + case 's': /* single-user (default, supported for sanity) */ + case 'S': + boothowto |= RB_SINGLE; + break; + + case 'v': + case 'V': + boothowto |= RB_VERBOSE; + bootverbose = 1; + break; + + default: + printf("Unrecognized boot flag '%c'.\n", *p); + break; + } + } + + /* + * Catch case of boot_verbose set in environment. + */ + if ((p = getenv("boot_verbose")) != NULL) { + if (strcmp(p, "yes") == 0 || strcmp(p, "YES") == 0) { + boothowto |= RB_VERBOSE; + bootverbose = 1; + } + } + + /* + * Initialize debuggers, and break into them if appropriate. + */ +#ifdef DDB + kdb_init(); + if (boothowto & RB_KDB) { + printf("Boot flags requested debugger\n"); + breakpoint(); + } +#endif +} + +void +bzero(void *buf, size_t len) +{ + caddr_t 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 +DELAY(int n) +{ + /* TODO */ +} + +/* + * Send an interrupt to process. + * + * Stack is set up to allow sigcode stored + * at top to call routine, followed by kcall + * to sigreturn routine below. After sigreturn + * resets the signal mask, the stack, and the + * frame pointer, it returns to the user + * specified pc, psl. + */ +void +sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +{ + struct proc *p = curproc; + struct trapframe *frame; + struct sigacts *psp = p->p_sigacts; + struct sigframe sf, *sfp; + u_int64_t sbs = 0; + int oonstack, rndfsize; + + frame = p->p_md.md_tf; + oonstack = (p->p_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0; + rndfsize = ((sizeof(sf) + 15) / 16) * 16; + + /* save user context */ + bzero(&sf, sizeof(struct sigframe)); + sf.sf_uc.uc_sigmask = *mask; + sf.sf_uc.uc_stack = p->p_sigstk; + sf.sf_uc.uc_mcontext.mc_flags = IA64_MC_FLAG_ONSTACK; + + sf.sf_uc.uc_mcontext.mc_nat = 0; /* XXX */ + sf.sf_uc.uc_mcontext.mc_sp = frame->tf_r[FRAME_SP]; + sf.sf_uc.uc_mcontext.mc_ip = frame->tf_cr_iip; + sf.sf_uc.uc_mcontext.mc_cfm = 0; /* XXX */ + sf.sf_uc.uc_mcontext.mc_um = frame->tf_cr_ipsr & 0x1fff; + sf.sf_uc.uc_mcontext.mc_ar_rsc = frame->tf_ar_rsc; + sf.sf_uc.uc_mcontext.mc_ar_bsp = frame->tf_ar_bsp; + sf.sf_uc.uc_mcontext.mc_ar_rnat = frame->tf_ar_rnat; + sf.sf_uc.uc_mcontext.mc_ar_ccv = frame->tf_ar_ccv; + sf.sf_uc.uc_mcontext.mc_ar_unat = frame->tf_ar_unat; + sf.sf_uc.uc_mcontext.mc_ar_fpsr = frame->tf_ar_fpsr; + sf.sf_uc.uc_mcontext.mc_ar_pfs = frame->tf_ar_pfs; + sf.sf_uc.uc_mcontext.mc_pr = frame->tf_pr; + + bcopy(&frame->tf_b[0], + &sf.sf_uc.uc_mcontext.mc_br[0], + 8 * sizeof(unsigned long)); + bcopy(&frame->tf_r[0], + &sf.sf_uc.uc_mcontext.mc_gr[0], + 31 * sizeof(unsigned long)); + + /* XXX mc_fr[] */ + + /* + * Allocate and validate space for the signal handler + * context. Note that if the stack is in P0 space, the + * call to grow() is a nop, and the useracc() check + * will fail if the process has not already allocated + * the space with a `brk'. + */ + if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + sbs = (u_int64_t) p->p_sigstk.ss_sp; + sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + + p->p_sigstk.ss_size - rndfsize); + p->p_sigstk.ss_flags |= SS_ONSTACK; + } else + sfp = (struct sigframe *)(frame->tf_r[FRAME_SP] - rndfsize); + + (void)grow_stack(p, (u_long)sfp); +#ifdef DEBUG + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, + sig, &sf, sfp); +#endif + if (!useracc((caddr_t)sfp, sizeof(sf), VM_PROT_WRITE)) { +#ifdef DEBUG + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sendsig(%d): useracc failed on sig %d\n", + p->p_pid, sig); +#endif + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + SIGACTION(p, SIGILL) = SIG_DFL; + SIGDELSET(p->p_sigignore, SIGILL); + SIGDELSET(p->p_sigcatch, SIGILL); + SIGDELSET(p->p_sigmask, SIGILL); + psignal(p, SIGILL); + return; + } + +#if 0 + /* save the floating-point state, if necessary, then copy it. */ + ia64_fpstate_save(p, 1); + sf.sf_uc.uc_mcontext.mc_ownedfp = p->p_md.md_flags & MDP_FPUSED; + bcopy(&p->p_addr->u_pcb.pcb_fp, + (struct fpreg *)sf.sf_uc.uc_mcontext.mc_fpregs, + sizeof(struct fpreg)); + sf.sf_uc.uc_mcontext.mc_fp_control = p->p_addr->u_pcb.pcb_fp_control; +#endif + +#ifdef COMPAT_OSF1 + /* + * XXX Create an OSF/1-style sigcontext and associated goo. + */ +#endif + + /* + * copy the frame out to userland. + */ + (void) copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)); +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sendsig(%d): sig %d sfp %p code %lx\n", p->p_pid, sig, + sfp, code); +#endif + + /* + * Set up the registers to return to sigcode. + */ + frame->tf_cr_iip = PS_STRINGS - (esigcode - sigcode); + frame->tf_r[FRAME_R1] = sig; + if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + frame->tf_r[FRAME_R2] = (u_int64_t)&(sfp->sf_si); + + /* Fill in POSIX parts */ + sf.sf_si.si_signo = sig; + sf.sf_si.si_code = code; + sf.sf_si.si_addr = (void*)frame->tf_cr_ifa; + } + else + frame->tf_r[FRAME_R2] = code; + + frame->tf_r[FRAME_R3] = (u_int64_t)&(sfp->sf_uc); + frame->tf_r[FRAME_R4] = (u_int64_t)catcher; + frame->tf_r[FRAME_R5] = sbs; + frame->tf_r[FRAME_SP] = (unsigned long)sfp; + +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, + frame->tf_cr_iip, frame->tf_regs[FRAME_R4]); + if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) + printf("sendsig(%d): sig %d returns\n", + p->p_pid, sig); +#endif +} + +/* + * System call to cleanup state after a signal + * has been taken. Reset signal mask and + * stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by + * context left by sendsig. Check carefully to + * make sure that the user has not modified the + * state to gain improper privileges. + */ +int +osigreturn(struct proc *p, + struct osigreturn_args /* { + struct osigcontext *sigcntxp; + } */ *uap) +{ + return EOPNOTSUPP; +} + +/* + * System call to cleanup state after a signal + * has been taken. Reset signal mask and + * stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by + * context left by sendsig. Check carefully to + * make sure that the user has not modified the + * state to gain improper privileges. + */ + +int +sigreturn(struct proc *p, + struct sigreturn_args /* { + ucontext_t *sigcntxp; + } */ *uap) +{ +#if 0 + ucontext_t uc, *ucp; + struct pcb *pcb; + unsigned long val; + + ucp = uap->sigcntxp; + pcb = &p->p_addr->u_pcb; + +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sigreturn: pid %d, scp %p\n", p->p_pid, ucp); +#endif + + /* + * Fetch the entire context structure at once for speed. + */ + if (copyin((caddr_t)ucp, (caddr_t)&uc, sizeof(ucontext_t))) + return (EFAULT); + + /* + * Restore the user-supplied information + */ + set_regs(p, (struct reg *)uc.uc_mcontext.mc_regs); + val = (uc.uc_mcontext.mc_regs[R_PS] | IA64_PSL_USERSET) & + ~IA64_PSL_USERCLR; + p->p_md.md_tf->tf_regs[FRAME_PS] = val; + p->p_md.md_tf->tf_regs[FRAME_PC] = uc.uc_mcontext.mc_regs[R_PC]; + ia64_pal_wrusp(uc.uc_mcontext.mc_regs[R_SP]); + + if (uc.uc_mcontext.mc_onstack & 1) + p->p_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigstk.ss_flags &= ~SS_ONSTACK; + + p->p_sigmask = uc.uc_sigmask; + SIG_CANTMASK(p->p_sigmask); + + /* XXX ksc.sc_ownedfp ? */ + ia64_fpstate_drop(p); + bcopy((struct fpreg *)uc.uc_mcontext.mc_fpregs, + &p->p_addr->u_pcb.pcb_fp, sizeof(struct fpreg)); + p->p_addr->u_pcb.pcb_fp_control = uc.uc_mcontext.mc_fp_control; + +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sigreturn(%d): returns\n", p->p_pid); +#endif +#endif + return (EJUSTRETURN); +} + +/* + * Machine dependent boot() routine + * + * I haven't seen anything to put here yet + * Possibly some stuff might be grafted back here from boot() + */ +void +cpu_boot(int howto) +{ +} + +/* + * Shutdown the CPU as much as possible + */ +void +cpu_halt(void) +{ + /* TODO */ +} + +/* + * Clear registers on exec + */ +void +setregs(struct proc *p, u_long entry, u_long stack, u_long ps_strings) +{ + /* TODO setup trapframe to enter CSU code at the right place */ +} + +int +ptrace_set_pc(struct proc *p, unsigned long addr) +{ + /* TODO set pc in trapframe */ + return 0; +} + +int +ptrace_single_step(struct proc *p) +{ + /* TODO arrange for user process to single step */ + return 0; +} + +int ptrace_read_u_check(struct proc *p, vm_offset_t addr, size_t len) +{ + vm_offset_t gap; + + if ((vm_offset_t) (addr + len) < addr) + return EPERM; + if ((vm_offset_t) (addr + len) <= sizeof(struct user)) + return 0; + + gap = (char *) p->p_md.md_tf - (char *) p->p_addr; + + if ((vm_offset_t) addr < gap) + return EPERM; + if ((vm_offset_t) (addr + len) <= + (vm_offset_t) (gap + sizeof(struct trapframe))) + return 0; + return EPERM; +} + +int +ptrace_write_u(struct proc *p, vm_offset_t off, long data) +{ + vm_offset_t min; +#if 0 + struct trapframe frame_copy; + struct trapframe *tp; +#endif + + /* + * Privileged kernel state is scattered all over the user area. + * Only allow write access to parts of regs and to fpregs. + */ + min = (char *)p->p_md.md_tf - (char *)p->p_addr; + if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) { +#if 0 + tp = p->p_md.md_tf; + frame_copy = *tp; + *(int *)((char *)&frame_copy + (off - min)) = data; + if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) || + !CS_SECURE(frame_copy.tf_cs)) + return (EINVAL); +#endif + *(int*)((char *)p->p_addr + off) = data; + return (0); + } + min = offsetof(struct user, u_pcb); + if (off >= min && off <= min + sizeof(struct pcb)) { + *(int*)((char *)p->p_addr + off) = data; + return (0); + } + return (EFAULT); +} + +int +ia64_pa_access(vm_offset_t pa) +{ + return VM_PROT_READ|VM_PROT_WRITE; +} + +int +fill_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + /* TODO copy trapframe to regs */ + return (0); +} + +int +set_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + /* TODO copy regs to trapframe */ + return (0); +} + +int +fill_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + /* TODO copy fpu state to fpregs */ + ia64_fpstate_save(p, 0); + +#if 0 + bcopy(&p->p_addr->u_pcb.pcb_fp, fpregs, sizeof *fpregs); +#endif + return (0); +} + +int +set_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + /* TODO copy fpregs fpu state */ + ia64_fpstate_drop(p); + +#if 0 + bcopy(fpregs, &p->p_addr->u_pcb.pcb_fp, sizeof *fpregs); +#endif + return (0); +} + +#ifndef DDB +void +Debugger(const char *msg) +{ + printf("Debugger(\"%s\") called.\n", msg); +} +#endif /* no DDB */ + +#include <sys/disklabel.h> + +/* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. Adjust transfer + * if needed, and signal errors or early completion. + */ +int +bounds_check_with_label(struct bio *bp, struct disklabel *lp, int wlabel) +{ +#if 0 + struct partition *p = lp->d_partitions + dkpart(bp->bio_dev); + int labelsect = lp->d_partitions[0].p_offset; + int maxsz = p->p_size, + sz = (bp->bio_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; + + /* overwriting disk label ? */ + /* XXX should also protect bootstrap in first 8K */ + if (bp->bio_blkno + p->p_offset <= LABELSECTOR + labelsect && +#if LABELSECTOR != 0 + bp->bio_blkno + p->p_offset + sz > LABELSECTOR + labelsect && +#endif + (bp->bio_cmd == BIO_WRITE) && wlabel == 0) { + bp->bio_error = EROFS; + goto bad; + } + +#if defined(DOSBBSECTOR) && defined(notyet) + /* overwriting master boot record? */ + if (bp->bio_blkno + p->p_offset <= DOSBBSECTOR && + (bp->bio_cmd == BIO_WRITE) && wlabel == 0) { + bp->bio_error = EROFS; + goto bad; + } +#endif + + /* beyond partition? */ + if (bp->bio_blkno < 0 || bp->bio_blkno + sz > maxsz) { + /* if exactly at end of disk, return an EOF */ + if (bp->bio_blkno == maxsz) { + bp->bio_resid = bp->bio_bcount; + return(0); + } + /* or truncate if part of it fits */ + sz = maxsz - bp->bio_blkno; + if (sz <= 0) { + bp->bio_error = EINVAL; + goto bad; + } + bp->bio_bcount = sz << DEV_BSHIFT; + } + + bp->bio_pblkno = bp->bio_blkno + p->p_offset; + return(1); + +bad: + bp->bio_flags |= BIO_ERROR; +#endif + return(-1); + +} + +static int +sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS) +{ + int error; + error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, + req); + if (!error && req->newptr) + resettodr(); + return (error); +} + +SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW, + &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", ""); + +SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, + CTLFLAG_RW, &disable_rtc_set, 0, ""); + +SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, + CTLFLAG_RW, &wall_cmos_clock, 0, ""); + +void +ia64_fpstate_check(struct proc *p) +{ +#if 0 + /* TODO panic if p has fp enabled and p != fpcurproc */ + if (p->p_addr->u_pcb.pcb_hw.apcb_flags & IA64_PCB_FLAGS_FEN) + if (p != fpcurproc) + panic("ia64_check_fpcurproc: bogus"); +#endif +} + +#define SET_FEN(p) /* TODO set fp enable for p */ + +#define CLEAR_FEN(p) /* TODO clear fp enable for p */ + +/* + * Save the floating point state in the pcb. Use this to get read-only + * access to the floating point state. If write is true, the current + * fp process is cleared so that fp state can safely be modified. The + * process will automatically reload the changed state by generating a + * FEN trap. + */ +void +ia64_fpstate_save(struct proc *p, int write) +{ +#if 0 + if (p == fpcurproc) { + /* + * If curproc != fpcurproc, then we need to enable FEN + * so that we can dump the fp state. + */ + ia64_pal_wrfen(1); + + /* + * Save the state in the pcb. + */ + savefpstate(&p->p_addr->u_pcb.pcb_fp); + + if (write) { + /* + * If fpcurproc == curproc, just ask the + * PALcode to disable FEN, otherwise we must + * clear the FEN bit in fpcurproc's pcb. + */ + if (fpcurproc == curproc) + ia64_pal_wrfen(0); + else + CLEAR_FEN(fpcurproc); + fpcurproc = NULL; + } else { + /* + * Make sure that we leave FEN enabled if + * curproc == fpcurproc. We must have at most + * one process with FEN enabled. Note that FEN + * must already be set in fpcurproc's pcb. + */ + if (curproc != fpcurproc) + ia64_pal_wrfen(0); + } + } +#endif +} + +/* + * Relinquish ownership of the FP state. This is called instead of + * ia64_save_fpstate() if the entire FP state is being changed + * (e.g. on sigreturn). + */ +void +ia64_fpstate_drop(struct proc *p) +{ +#if 0 + if (p == fpcurproc) { + if (p == curproc) { + /* + * Disable FEN via the PALcode. This will + * clear the bit in the pcb as well. + */ + ia64_pal_wrfen(0); + } else { + /* + * Clear the FEN bit of the pcb. + */ + CLEAR_FEN(p); + } + fpcurproc = NULL; + } +#endif +} + +/* + * Switch the current owner of the fp state to p, reloading the state + * from the pcb. + */ +void +ia64_fpstate_switch(struct proc *p) +{ +#if 0 + /* + * Enable FEN so that we can access the fp registers. + */ + ia64_pal_wrfen(1); + if (fpcurproc) { + /* + * Dump the old fp state if its valid. + */ + savefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); + CLEAR_FEN(fpcurproc); + } + + /* + * Remember the new FP owner and reload its state. + */ + fpcurproc = p; + restorefpstate(&fpcurproc->p_addr->u_pcb.pcb_fp); + + /* + * If the new owner is curproc, leave FEN enabled, otherwise + * mark its PCB so that it gets FEN when we context switch to + * it later. + */ + if (p != curproc) { + ia64_pal_wrfen(0); + SET_FEN(p); + } + + p->p_md.md_flags |= MDP_FPUSED; +#endif +} diff --git a/sys/ia64/ia64/mem.c b/sys/ia64/ia64/mem.c new file mode 100644 index 0000000..b3f5531 --- /dev/null +++ b/sys/ia64/ia64/mem.c @@ -0,0 +1,296 @@ +/*- + * 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. + * 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: Utah $Hdr: mem.c 1.13 89/10/08$ + * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 + * $FreeBSD$ + */ + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/memrange.h> +#include <sys/proc.h> +#include <sys/msgbuf.h> +#include <sys/systm.h> +#include <sys/signalvar.h> +#include <sys/uio.h> + +#include <machine/frame.h> +#ifdef PERFMON +#include <machine/perfmon.h> +#endif + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +static dev_t memdev, kmemdev; +#ifdef PERFMON +static dev_t perfdev; +#endif /* PERFMON */ + +static d_open_t mmopen; +static d_close_t mmclose; +static d_read_t mmrw; +static d_ioctl_t mmioctl; +static d_mmap_t memmmap; + +#define CDEV_MAJOR 2 +static struct cdevsw mem_cdevsw = { + /* open */ mmopen, + /* close */ mmclose, + /* read */ mmrw, + /* write */ mmrw, + /* ioctl */ mmioctl, + /* poll */ (d_poll_t *)seltrue, + /* mmap */ memmmap, + /* strategy */ nostrategy, + /* name */ "mem", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ D_MEM, + /* bmaj */ -1 +}; + +#if NHWI > 0 +#define ICU_LEN (NHWI) +#else +#define ICU_LEN (NSWI) +#endif + +struct mem_range_softc mem_range_softc; + +static int +mmclose(dev_t dev, int flags, int fmt, struct proc *p) +{ + switch (minor(dev)) { +#ifdef PERFMON + case 32: + return perfmon_close(dev, flags, fmt, p); +#endif + default: + break; + } + return (0); +} + +static int +mmopen(dev_t dev, int flags, int fmt, struct proc *p) +{ + + switch (minor(dev)) { + case 0: + case 1: + if ((flags & FWRITE) && securelevel > 0) + return (EPERM); + break; + case 32: +#ifdef PERFMON + return perfmon_open(dev, flags, fmt, p); +#else + return ENODEV; +#endif + default: + break; + } + return (0); +} + +/*ARGSUSED*/ +static int +mmrw(dev_t dev, struct uio *uio, int flags) +{ + vm_offset_t o, v; + int c = 0; + struct iovec *iov; + int error = 0, rw; + vm_offset_t addr, eaddr; + + 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("mmrw"); + continue; + } + switch (minor(dev)) { + +/* minor device 0 is physical memory */ + case 0: + v = uio->uio_offset; +kmemphys: + /* Allow reads only in RAM. */ + rw = (uio->uio_rw == UIO_READ) ? VM_PROT_READ : VM_PROT_WRITE; + if ((ia64_pa_access(v) & rw) != rw) { + error = EFAULT; + c = 0; + break; + } + + o = uio->uio_offset & PAGE_MASK; + c = min(uio->uio_resid, (int)(PAGE_SIZE - o)); + error = + uiomove((caddr_t)IA64_PHYS_TO_RR7(v), c, uio); + continue; + +/* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + + if (v >= IA64_RR_BASE(6)) { + v = IA64_RR_MASK(v); + goto kmemphys; + } + + c = min(iov->iov_len, MAXPHYS); + /* + * Make sure that all of the pages are currently resident so + * that we don't create any zero-fill pages. + */ + addr = trunc_page(v); + eaddr = round_page(v + c); + for (; addr < eaddr; addr += PAGE_SIZE) + if (pmap_extract(kernel_pmap, addr) == 0) + return EFAULT; + if (!kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? + VM_PROT_READ : VM_PROT_WRITE)) + return (EFAULT); + error = uiomove((caddr_t)v, c, uio); + } + + if (error) + break; + iov->iov_base += c; + iov->iov_len -= c; + uio->uio_offset += c; + uio->uio_resid -= c; + } + return (error); +} + +/*******************************************************\ +* allow user processes to MMAP some memory sections * +* instead of going through read/write * +\*******************************************************/ +static int +memmmap(dev_t dev, vm_offset_t offset, 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) != 0) + return (-1); + + /* + * Allow access only in RAM. + */ + if ((prot & ia64_pa_access(atop((vm_offset_t)offset))) != prot) + return (-1); + return (ia64_btop(IA64_PHYS_TO_RR7(offset))); +} + +static int +mmioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, struct proc *p) +{ + switch(minor(dev)) { +#ifdef PERFMON + case 32: + return perfmon_ioctl(dev, cmd, cmdarg, flags, p); +#endif + default: + return ENODEV; + } + + return (0); +} + +static int +mem_modevent(module_t mod, int type, void *data) +{ + switch(type) { + case MOD_LOAD: + if (bootverbose) + printf("mem: <memory & I/O>\n"); +/* XXX - ??? */ +#if 0 + /* Initialise memory range handling */ + if (mem_range_softc.mr_op != NULL) + mem_range_softc.mr_op->init(&mem_range_softc); +#endif + + memdev = make_dev(&mem_cdevsw, 0, UID_ROOT, GID_KMEM, + 0640, "mem"); + kmemdev = make_dev(&mem_cdevsw, 1, UID_ROOT, GID_KMEM, + 0640, "kmem"); +#ifdef PERFMON + perfdev = make_dev(&mem_cdevsw, 32, UID_ROOT, GID_KMEM, + 0640, "perfmon"); +#endif /* PERFMON */ + return 0; + + case MOD_UNLOAD: + destroy_dev(memdev); + destroy_dev(kmemdev); +#ifdef PERFMON + destroy_dev(perfdev); +#endif /* PERFMON */ + return 0; + + case MOD_SHUTDOWN: + return 0; + + default: + return EOPNOTSUPP; + } +} + +DEV_MODULE(mem, mem_modevent, NULL); diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c new file mode 100644 index 0000000..6dea327 --- /dev/null +++ b/sys/ia64/ia64/mp_machdep.c @@ -0,0 +1,789 @@ +/*- + * 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 <machine/mutex.h> +#include <sys/ktr.h> +#include <sys/proc.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <sys/user.h> +#include <sys/dkstat.h> + +#include <machine/smp.h> +#include <machine/lock.h> +#include <machine/atomic.h> +#include <machine/ipl.h> +#include <machine/globaldata.h> +#include <machine/pmap.h> +#include <machine/clock.h> + +#define CHECKSTATE_USER 0 +#define CHECKSTATE_SYS 1 +#define CHECKSTATE_INTR 2 + +volatile u_int stopped_cpus; +volatile u_int started_cpus; +volatile u_int checkstate_probed_cpus; +volatile u_int checkstate_need_ast; +volatile u_int checkstate_pending_ast; +struct proc* checkstate_curproc[NCPUS]; +int checkstate_cpustate[NCPUS]; +u_long checkstate_pc[NCPUS]; +volatile u_int resched_cpus; +void (*cpustop_restartfunc) __P((void)); +int mp_ncpus; + +int smp_started; +int boot_cpu_id; +u_int32_t all_cpus; + +static struct globaldata *cpuno_to_globaldata[NCPUS]; + +int smp_active = 0; /* are the APs allowed to run? */ +SYSCTL_INT(_machdep, OID_AUTO, smp_active, CTLFLAG_RW, &smp_active, 0, ""); + +/* Is forwarding of a interrupt to the CPU holding the ISR lock enabled ? */ +int forward_irq_enabled = 1; +SYSCTL_INT(_machdep, OID_AUTO, forward_irq_enabled, CTLFLAG_RW, + &forward_irq_enabled, 0, ""); + +/* Enable forwarding of a signal to a process running on a different CPU */ +static int forward_signal_enabled = 1; +SYSCTL_INT(_machdep, OID_AUTO, forward_signal_enabled, CTLFLAG_RW, + &forward_signal_enabled, 0, ""); + +/* Enable forwarding of roundrobin to all other cpus */ +static int forward_roundrobin_enabled = 1; +SYSCTL_INT(_machdep, OID_AUTO, forward_roundrobin_enabled, CTLFLAG_RW, + &forward_roundrobin_enabled, 0, ""); + +/* + * Initialise a struct globaldata. + */ +void +globaldata_init(struct globaldata *globaldata, int cpuno, size_t sz) +{ + bzero(globaldata, sz); + globaldata->gd_cpuno = cpuno; + globaldata->gd_other_cpus = all_cpus & ~(1 << cpuno); + globaldata->gd_next_asn = 0; + globaldata->gd_current_asngen = 1; + cpuno_to_globaldata[cpuno] = globaldata; +} + +struct globaldata * +globaldata_find(int cpuno) +{ + return cpuno_to_globaldata[cpuno]; +} + +/* Implementation of simplelocks */ + +void +s_lock_init(struct simplelock *lkp) +{ + lkp->lock_data = 0; +} + +void +s_lock(struct simplelock *lkp) +{ + for (;;) { + if (s_lock_try(lkp)) + return; + + /* + * Spin until clear. + */ + while (lkp->lock_data) + ; + } +} + +int +s_lock_try(struct simplelock *lkp) +{ + return 0; /* XXX needed? */ +} + +/* Other stuff */ + +/* lock around the MP rendezvous */ +static struct mtx smp_rv_lock; + +static void +init_locks(void) +{ + mtx_init(&smp_rv_lock, "smp_rendezvous", MTX_SPIN); +} + +void +mp_start() +{ + init_locks(); +} + +void +mp_announce() +{ +} + +void +smp_invltlb() +{ +} + +#define GD_TO_INDEX(pc, prof) \ + ((int)(((u_quad_t)((pc) - (prof)->pr_off) * \ + (u_quad_t)((prof)->pr_scale)) >> 16) & ~1) + +static void +addugd_intr_forwarded(struct proc *p, int id, int *astmap) +{ + int i; + struct uprof *prof; + u_long pc; + + pc = checkstate_pc[id]; + prof = &p->p_stats->p_prof; + if (pc >= prof->pr_off && + (i = GD_TO_INDEX(pc, prof)) < prof->pr_size) { + if ((p->p_flag & P_OWEUPC) == 0) { + prof->pr_addr = pc; + prof->pr_ticks = 1; + p->p_flag |= P_OWEUPC; + } + *astmap |= (1 << id); + } +} + +static void +forwarded_statclock(int id, int pscnt, int *astmap) +{ + struct pstats *pstats; + long rss; + struct rusage *ru; + struct vmspace *vm; + int cpustate; + struct proc *p; +#ifdef GPROF + register struct gmonparam *g; + int i; +#endif + + p = checkstate_curproc[id]; + cpustate = checkstate_cpustate[id]; + + switch (cpustate) { + case CHECKSTATE_USER: + if (p->p_flag & P_PROFIL) + addugd_intr_forwarded(p, id, astmap); + if (pscnt > 1) + return; + p->p_uticks++; + if (p->p_nice > NZERO) + cp_time[CP_NICE]++; + else + cp_time[CP_USER]++; + break; + case CHECKSTATE_SYS: +#ifdef GPROF + /* + * Kernel statistics are just like addugd_intr, only easier. + */ + g = &_gmonparam; + if (g->state == GMON_PROF_ON) { + i = checkstate_pc[id] - g->lowpc; + if (i < g->textsize) { + i /= HISTFRACTION * sizeof(*g->kcount); + g->kcount[i]++; + } + } +#endif + if (pscnt > 1) + return; + + if (!p) + cp_time[CP_IDLE]++; + else { + p->p_sticks++; + cp_time[CP_SYS]++; + } + break; + case CHECKSTATE_INTR: + default: +#ifdef GPROF + /* + * Kernel statistics are just like addugd_intr, only easier. + */ + g = &_gmonparam; + if (g->state == GMON_PROF_ON) { + i = checkstate_pc[id] - g->lowpc; + if (i < g->textsize) { + i /= HISTFRACTION * sizeof(*g->kcount); + g->kcount[i]++; + } + } +#endif + if (pscnt > 1) + return; + if (p) + p->p_iticks++; + cp_time[CP_INTR]++; + } + if (p != NULL) { + schedclock(p); + + /* Update resource usage integrals and maximums. */ + if ((pstats = p->p_stats) != NULL && + (ru = &pstats->p_ru) != NULL && + (vm = p->p_vmspace) != NULL) { + ru->ru_ixrss += pgtok(vm->vm_tsize); + ru->ru_idrss += pgtok(vm->vm_dsize); + ru->ru_isrss += pgtok(vm->vm_ssize); + rss = pgtok(vmspace_resident_count(vm)); + if (ru->ru_maxrss < rss) + ru->ru_maxrss = rss; + } + } +} + +#define BETTER_CLOCK_DIAGNOSTIC + +void +forward_statclock(int pscnt) +{ + int map; + int id; + int i; + + /* Kludge. We don't yet have separate locks for the interrupts + * and the kernel. This means that we cannot let the other processors + * handle complex interrupts while inhibiting them from entering + * the kernel in a non-interrupt context. + * + * What we can do, without changing the locking mechanisms yet, + * is letting the other processors handle a very simple interrupt + * (wich determines the processor states), and do the main + * work ourself. + */ + + CTR1(KTR_SMP, "forward_statclock(%d)", pscnt); + + if (!smp_started || cold || panicstr) + return; + + /* Step 1: Probe state (user, cpu, interrupt, spinlock, idle ) */ + + map = PCPU_GET(other_cpus) & ~stopped_cpus ; + checkstate_probed_cpus = 0; + if (map != 0) + smp_ipi_selected(map, IPI_CHECKSTATE); + + i = 0; + while (checkstate_probed_cpus != map) { + /* spin */ + i++; + if (i == 100000) { +#ifdef BETTER_CLOCK_DIAGNOSTIC + printf("forward_statclock: checkstate %x\n", + checkstate_probed_cpus); +#endif + break; + } + } + + /* + * Step 2: walk through other processors processes, update ticks and + * profiling info. + */ + + map = 0; + for (id = 0; id < mp_ncpus; id++) { + if (id == cpuid) + continue; + if (((1 << id) & checkstate_probed_cpus) == 0) + continue; + forwarded_statclock(id, pscnt, &map); + } + if (map != 0) { + checkstate_need_ast |= map; + smp_ipi_selected(map, IPI_AST); + i = 0; + while ((checkstate_need_ast & map) != 0) { + /* spin */ + i++; + if (i > 100000) { +#ifdef BETTER_CLOCK_DIAGNOSTIC + printf("forward_statclock: dropped ast 0x%x\n", + checkstate_need_ast & map); +#endif + break; + } + } + } +} + +void +forward_hardclock(int pscnt) +{ + int map; + int id; + struct proc *p; + struct pstats *pstats; + int i; + + /* Kludge. We don't yet have separate locks for the interrupts + * and the kernel. This means that we cannot let the other processors + * handle complex interrupts while inhibiting them from entering + * the kernel in a non-interrupt context. + * + * What we can do, without changing the locking mechanisms yet, + * is letting the other processors handle a very simple interrupt + * (wich determines the processor states), and do the main + * work ourself. + */ + + CTR1(KTR_SMP, "forward_hardclock(%d)", pscnt); + + if (!smp_started || cold || panicstr) + return; + + /* Step 1: Probe state (user, cpu, interrupt, spinlock, idle) */ + + map = PCPU_GET(other_cpus) & ~stopped_cpus ; + checkstate_probed_cpus = 0; + if (map != 0) + smp_ipi_selected(map, IPI_CHECKSTATE); + + i = 0; + while (checkstate_probed_cpus != map) { + /* spin */ + i++; + if (i == 100000) { +#ifdef BETTER_CLOCK_DIAGNOSTIC + printf("forward_hardclock: checkstate %x\n", + checkstate_probed_cpus); +#endif + breakpoint(); + break; + } + } + + /* + * Step 2: walk through other processors processes, update virtual + * timer and profiling timer. If stathz == 0, also update ticks and + * profiling info. + */ + + map = 0; + for (id = 0; id < mp_ncpus; id++) { + if (id == cpuid) + continue; + if (((1 << id) & checkstate_probed_cpus) == 0) + continue; + p = checkstate_curproc[id]; + if (p) { + pstats = p->p_stats; + if (checkstate_cpustate[id] == CHECKSTATE_USER && + timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) && + itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) { + psignal(p, SIGVTALRM); + map |= (1 << id); + } + if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) && + itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) { + psignal(p, SIGPROF); + map |= (1 << id); + } + } + if (stathz == 0) { + forwarded_statclock( id, pscnt, &map); + } + } + if (map != 0) { + checkstate_need_ast |= map; + smp_ipi_selected(map, IPI_AST); + i = 0; + while ((checkstate_need_ast & map) != 0) { + /* spin */ + i++; + if (i > 100000) { +#ifdef BETTER_CLOCK_DIAGNOSTIC + printf("forward_hardclock: dropped ast 0x%x\n", + checkstate_need_ast & map); +#endif + break; + } + } + } +} + +void +forward_signal(struct proc *p) +{ + int map; + int id; + int i; + + /* Kludge. We don't yet have separate locks for the interrupts + * and the kernel. This means that we cannot let the other processors + * handle complex interrupts while inhibiting them from entering + * the kernel in a non-interrupt context. + * + * What we can do, without changing the locking mechanisms yet, + * is letting the other processors handle a very simple interrupt + * (wich determines the processor states), and do the main + * work ourself. + */ + + CTR1(KTR_SMP, "forward_signal(%p)", p); + + if (!smp_started || cold || panicstr) + return; + if (!forward_signal_enabled) + return; + while (1) { + if (p->p_stat != SRUN) + return; + id = p->p_oncpu; + if (id == 0xff) + return; + map = (1<<id); + checkstate_need_ast |= map; + smp_ipi_selected(map, IPI_AST); + i = 0; + while ((checkstate_need_ast & map) != 0) { + /* spin */ + i++; + if (i > 100000) { +#if 0 + printf("forward_signal: dropped ast 0x%x\n", + checkstate_need_ast & map); +#endif + break; + } + } + if (id == p->p_oncpu) + return; + } +} + +void +forward_roundrobin(void) +{ + u_int map; + int i; + + CTR0(KTR_SMP, "forward_roundrobin()"); + + if (!smp_started || cold || panicstr) + return; + if (!forward_roundrobin_enabled) + return; + resched_cpus |= PCPU_GET(other_cpus); + map = PCPU_GET(other_cpus) & ~stopped_cpus ; + smp_ipi_selected(map, IPI_AST); + i = 0; + while ((checkstate_need_ast & map) != 0) { + /* spin */ + i++; + if (i > 100000) { +#if 0 + printf("forward_roundrobin: dropped ast 0x%x\n", + checkstate_need_ast & map); +#endif + break; + } + } +} + +/* + * When called the executing CPU will send an IPI to all other CPUs + * requesting that they halt execution. + * + * Usually (but not necessarily) called with 'other_cpus' as its arg. + * + * - Signals all CPUs in map to stop. + * - Waits for each to stop. + * + * Returns: + * -1: error + * 0: NA + * 1: ok + * + * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs + * from executing at same time. + */ +int +stop_cpus(u_int map) +{ + int i; + + if (!smp_started) + return 0; + + CTR1(KTR_SMP, "stop_cpus(%x)", map); + + /* send the stop IPI to all CPUs in map */ + smp_ipi_selected(map, IPI_STOP); + + i = 0; + while ((stopped_cpus & map) != map) { + /* spin */ + i++; + if (i == 100000) { + printf("timeout stopping cpus\n"); + break; + } + ia64_mf(); + } + + printf("stopped_cpus=%x\n", stopped_cpus); + + return 1; +} + + +/* + * Called by a CPU to restart stopped CPUs. + * + * Usually (but not necessarily) called with 'stopped_cpus' as its arg. + * + * - Signals all CPUs in map to restart. + * - Waits for each to restart. + * + * Returns: + * -1: error + * 0: NA + * 1: ok + */ +int +restart_cpus(u_int map) +{ + if (!smp_started) + return 0; + + CTR1(KTR_SMP, "restart_cpus(%x)", map); + + started_cpus = map; /* signal other cpus to restart */ + ia64_mf(); + + while ((stopped_cpus & map) != 0) /* wait for each to clear its bit */ + ia64_mf(); + + return 1; +} + +/* + * All-CPU rendezvous. CPUs are signalled, all execute the setup function + * (if specified), rendezvous, execute the action function (if specified), + * rendezvous again, execute the teardown function (if specified), and then + * resume. + * + * Note that the supplied external functions _must_ be reentrant and aware + * that they are running in parallel and in an unknown lock context. + */ +static void (*smp_rv_setup_func)(void *arg); +static void (*smp_rv_action_func)(void *arg); +static void (*smp_rv_teardown_func)(void *arg); +static void *smp_rv_func_arg; +static volatile int smp_rv_waiters[2]; + +void +smp_rendezvous_action(void) +{ + /* setup function */ + if (smp_rv_setup_func != NULL) + smp_rv_setup_func(smp_rv_func_arg); + /* spin on entry rendezvous */ + atomic_add_int(&smp_rv_waiters[0], 1); + while (smp_rv_waiters[0] < mp_ncpus) + ; + /* action function */ + if (smp_rv_action_func != NULL) + smp_rv_action_func(smp_rv_func_arg); + /* spin on exit rendezvous */ + atomic_add_int(&smp_rv_waiters[1], 1); + while (smp_rv_waiters[1] < mp_ncpus) + ; + /* teardown function */ + if (smp_rv_teardown_func != NULL) + smp_rv_teardown_func(smp_rv_func_arg); +} + +void +smp_rendezvous(void (* setup_func)(void *), + void (* action_func)(void *), + void (* teardown_func)(void *), + void *arg) +{ + /* obtain rendezvous lock */ + mtx_enter(&smp_rv_lock, MTX_SPIN); /* XXX sleep here? NOWAIT flag? */ + + /* set static function pointers */ + smp_rv_setup_func = setup_func; + smp_rv_action_func = action_func; + smp_rv_teardown_func = teardown_func; + smp_rv_func_arg = arg; + smp_rv_waiters[0] = 0; + smp_rv_waiters[1] = 0; + + /* signal other processors, which will enter the IPI with interrupts off */ + smp_ipi_all_but_self(IPI_RENDEZVOUS); + + /* call executor function */ + smp_rendezvous_action(); + + /* release lock */ + mtx_exit(&smp_rv_lock, MTX_SPIN); +} + +/* + * send an IPI to a set of cpus. + */ +void +smp_ipi_selected(u_int32_t cpus, u_int64_t ipi) +{ + struct globaldata *globaldata; + + CTR2(KTR_SMP, "smp_ipi_selected: cpus: %x ipi: %lx", cpus, ipi); + ia64_mf(); + while (cpus) { + int cpuno = ffs(cpus) - 1; + cpus &= ~(1 << cpuno); + + globaldata = cpuno_to_globaldata[cpuno]; + if (globaldata) { + atomic_set_64(&globaldata->gd_pending_ipis, ipi); + ia64_mf(); +#if 0 + CTR1(KTR_SMP, "calling alpha_pal_wripir(%d)", cpuno); + alpha_pal_wripir(cpuno); +#endif + } + } +} + +/* + * send an IPI INTerrupt containing 'vector' to all CPUs, including myself + */ +void +smp_ipi_all(u_int64_t ipi) +{ + smp_ipi_selected(all_cpus, ipi); +} + +/* + * send an IPI to all CPUs EXCEPT myself + */ +void +smp_ipi_all_but_self(u_int64_t ipi) +{ + smp_ipi_selected(PCPU_GET(other_cpus), ipi); +} + +/* + * send an IPI to myself + */ +void +smp_ipi_self(u_int64_t ipi) +{ + smp_ipi_selected(1 << PCPU_GET(cpuno), ipi); +} + +/* + * Handle an IPI sent to this processor. + */ +void +smp_handle_ipi(struct trapframe *frame) +{ + u_int64_t ipis; + u_int64_t ipi; + int cpuno = PCPU_GET(cpuno); + + do { + ipis = PCPU_GET(pending_ipis); + } while (atomic_cmpset_64(&PCPU_GET(pending_ipis), ipis, 0)); + + CTR1(KTR_SMP, "smp_handle_ipi(), ipis=%lx", ipis); + while (ipis) { + /* + * Find the lowest set bit. + */ + ipi = ipis & ~(ipis - 1); + switch (ipi) { + case IPI_INVLTLB: + break; + + case IPI_RENDEZVOUS: + CTR0(KTR_SMP, "IPI_RENDEZVOUS"); + smp_rendezvous_action(); + break; + + case IPI_AST: + CTR0(KTR_SMP, "IPI_AST"); + atomic_clear_int(&checkstate_need_ast, 1<<cpuno); + atomic_set_int(&checkstate_pending_ast, 1<<cpuno); + if ((frame->tf_cr_ipsr & IA64_PSR_CPL) + == IA64_PSR_CPL_USER) + ast(frame); /* XXX */ + break; + + case IPI_CHECKSTATE: + CTR0(KTR_SMP, "IPI_CHECKSTATE"); + if ((frame->tf_cr_ipsr & IA64_PSR_CPL) + == IA64_PSR_CPL_USER) + checkstate_cpustate[cpuno] = CHECKSTATE_USER; + else if (PCPU_GET(intr_nesting_level) == 1) + checkstate_cpustate[cpuno] = CHECKSTATE_SYS; + else + checkstate_cpustate[cpuno] = CHECKSTATE_INTR; + checkstate_curproc[cpuno] = PCPU_GET(curproc); + atomic_set_int(&checkstate_probed_cpus, 1<<cpuno); + break; + + case IPI_STOP: + CTR0(KTR_SMP, "IPI_STOP"); + atomic_set_int(&stopped_cpus, 1<<cpuno); + while ((started_cpus & (1<<cpuno)) == 0) + ia64_mf(); + atomic_clear_int(&started_cpus, 1<<cpuno); + atomic_clear_int(&stopped_cpus, 1<<cpuno); + break; + } + } +} diff --git a/sys/ia64/ia64/pal.S b/sys/ia64/ia64/pal.S new file mode 100644 index 0000000..081117c --- /dev/null +++ b/sys/ia64/ia64/pal.S @@ -0,0 +1,71 @@ +/*- + * 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 <machine/asm.h> + +BSS(ia64_pal_entry, 8) + +/* + * struct ia64_pal_result ia64_call_pal_static(u_int64_t proc, + u_int64_t arg1, u_int64_t arg2, u_int64_t arg3) + */ + NESTED(ia64_call_pal_static, 4, 5, 0, r39, r40) + +palret = loc0 +entry = loc1 +rpsave = loc2 +pfssave = loc3 +psrsave = loc4 + + movl entry=ia64_pal_entry +1: mov palret=ip // for return address + mov rpsave=rp + ;; + mov psrsave=psr + mov r28=in0 // procedure number + ;; + ld8 entry=[entry] // read entry point + mov r29=in1 // copy arguments + mov r30=in2 + mov r31=in3 + ;; + mov b1=entry + add palret=2f-1b,palret // calculate return address + ;; + mov b0=palret + rsm psr.i // disable interrupts + ;; + br.cond.sptk b1 // call into firmware +2: mov psr.l=psrsave + mov b0=rpsave + mov ar.pfs=pfssave + ;; + srlz.d + br.ret.sptk b0 + + END(ia64_call_pal_static)
\ No newline at end of file diff --git a/sys/ia64/ia64/pal.s b/sys/ia64/ia64/pal.s new file mode 100644 index 0000000..081117c --- /dev/null +++ b/sys/ia64/ia64/pal.s @@ -0,0 +1,71 @@ +/*- + * 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 <machine/asm.h> + +BSS(ia64_pal_entry, 8) + +/* + * struct ia64_pal_result ia64_call_pal_static(u_int64_t proc, + u_int64_t arg1, u_int64_t arg2, u_int64_t arg3) + */ + NESTED(ia64_call_pal_static, 4, 5, 0, r39, r40) + +palret = loc0 +entry = loc1 +rpsave = loc2 +pfssave = loc3 +psrsave = loc4 + + movl entry=ia64_pal_entry +1: mov palret=ip // for return address + mov rpsave=rp + ;; + mov psrsave=psr + mov r28=in0 // procedure number + ;; + ld8 entry=[entry] // read entry point + mov r29=in1 // copy arguments + mov r30=in2 + mov r31=in3 + ;; + mov b1=entry + add palret=2f-1b,palret // calculate return address + ;; + mov b0=palret + rsm psr.i // disable interrupts + ;; + br.cond.sptk b1 // call into firmware +2: mov psr.l=psrsave + mov b0=rpsave + mov ar.pfs=pfssave + ;; + srlz.d + br.ret.sptk b0 + + END(ia64_call_pal_static)
\ No newline at end of file diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c new file mode 100644 index 0000000..f448de9 --- /dev/null +++ b/sys/ia64/ia64/pmap.c @@ -0,0 +1,2388 @@ +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * Copyright (c) 1994 John S. Dyson + * All rights reserved. + * Copyright (c) 1994 David Greenman + * All rights reserved. + * Copyright (c) 1998,2000 Doug Rabson + * 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 of UUNET Technologies 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 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: @(#)pmap.c 7.7 (Berkeley) 5/12/91 + * from: i386 Id: pmap.c,v 1.193 1998/04/19 15:22:48 bde Exp + * with some ideas from NetBSD's alpha pmap + * $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 virtual-to-physical 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 or 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. + */ + +/* + * Following the Linux model, region IDs are allocated in groups of + * eight so that a single region ID can be used for as many RRs as we + * want by encoding the RR number into the low bits of the ID. + * + * We reserve region ID 0 for the kernel and allocate the remaining + * IDs for user pmaps. + * + * Region 0..4 + * User virtually mapped + * + * Region 5 + * Kernel virtually mapped + * + * Region 6 + * Kernel physically mapped uncacheable + * + * Region 7 + * Kernel physically mapped cacheable + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/msgbuf.h> +#include <sys/vmmeter.h> +#include <sys/mman.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <sys/lock.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/vm_zone.h> + +#include <sys/user.h> + +#include <machine/md_var.h> + +#ifndef PMAP_SHPGPERPROC +#define PMAP_SHPGPERPROC 200 +#endif + +#if defined(DIAGNOSTIC) +#define PMAP_DIAGNOSTIC +#endif + +#define MINPV 2048 + +#if 0 +#define PMAP_DIAGNOSTIC +#define PMAP_DEBUG +#endif + +#if !defined(PMAP_DIAGNOSTIC) +#define PMAP_INLINE __inline +#else +#define PMAP_INLINE +#endif + +#if 0 + +static void +pmap_break(void) +{ +} + +/* #define PMAP_DEBUG_VA(va) if ((va) == 0x120058000) pmap_break(); else */ + +#endif + +#ifndef PMAP_DEBUG_VA +#define PMAP_DEBUG_VA(va) do {} while(0) +#endif + +/* + * Get PDEs and PTEs for user/kernel address space + */ +#define pmap_pte_w(pte) ((pte)->pte_ig & PTE_IG_WIRED) +#define pmap_pte_managed(pte) ((pte)->pte_ig & PTE_IG_MANAGED) +#define pmap_pte_v(pte) ((pte)->pte_p) +#define pmap_pte_pa(pte) (((pte)->pte_ppn) << 12) +#define pmap_pte_prot(pte) (((pte)->pte_ar << 2) | (pte)->pte_pl) + +#define pmap_pte_set_w(pte, v) ((v)?((pte)->pte_ig |= PTE_IG_WIRED) \ + :((pte)->pte_ig &= ~PTE_IG_WIRED)) +#define pmap_pte_set_prot(pte, v) do { \ + (pte)->pte_ar = v >> 2; \ + (pte)->pte_pl = v & 3; \ +} while (0) + +/* + * Given a map and a machine independent protection code, + * convert to an ia64 protection code. + */ +#define pte_prot(m, p) (protection_codes[m == pmap_kernel() ? 0 : 1][p]) +int protection_codes[2][8]; + +/* + * Return non-zero if this pmap is currently active + */ +#define pmap_isactive(pmap) (pmap->pm_active) + +/* + * Statically allocated kernel pmap + */ +static struct pmap kernel_pmap_store; +pmap_t kernel_pmap; + +vm_offset_t avail_start; /* PA of first available physical page */ +vm_offset_t avail_end; /* PA of last available physical page */ +vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ +vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ +static boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ + + +vm_offset_t kernel_vm_end; + +/* + * Data for the ASN allocator + */ +static int pmap_maxasn; +static int pmap_nextasn = 0; +static u_int pmap_current_asngen = 1; +static pmap_t pmap_active = 0; + +/* + * Data for the pv entry allocation mechanism + */ +static vm_zone_t pvzone; +static struct vm_zone pvzone_store; +static struct vm_object pvzone_obj; +static vm_zone_t pvbootzone; +static struct vm_zone pvbootzone_store; +static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0; +static int pmap_pagedaemon_waken = 0; +static struct pv_entry *pvinit; +static struct pv_entry *pvbootinit; + +static PMAP_INLINE void free_pv_entry __P((pv_entry_t pv)); +static pv_entry_t get_pv_entry __P((void)); +static void ia64_protection_init __P((void)); +static void pmap_changebit __P((vm_page_t m, int bit, boolean_t setem)); + +static void pmap_remove_all __P((vm_page_t m)); +static void pmap_enter_quick __P((pmap_t pmap, vm_offset_t va, vm_page_t m)); +static boolean_t pmap_is_referenced __P((vm_page_t m)); + +vm_offset_t +pmap_steal_memory(vm_size_t size) +{ + vm_size_t bank_size; + vm_offset_t pa, va; + + size = round_page(size); + + bank_size = phys_avail[1] - phys_avail[0]; + while (size > bank_size) { + int i; + for (i = 0; phys_avail[i+2]; i+= 2) { + phys_avail[i] = phys_avail[i+2]; + phys_avail[i+1] = phys_avail[i+3]; + } + phys_avail[i] = 0; + phys_avail[i+1] = 0; + if (!phys_avail[0]) + panic("pmap_steal_memory: out of memory"); + bank_size = phys_avail[1] - phys_avail[0]; + } + + pa = phys_avail[0]; + phys_avail[0] += size; + + va = IA64_PHYS_TO_RR7(pa); + bzero((caddr_t) va, size); + return va; +} + +/* + * Bootstrap the system enough to run with virtual memory. + */ +void +pmap_bootstrap() +{ + int i; + int boot_pvs; + + /* + * Setup ASNs + */ + pmap_nextasn = 0; + pmap_maxasn = 0; + pmap_current_asngen = 1; + + avail_start = phys_avail[0]; + for (i = 0; phys_avail[i+2]; i+= 2) ; + avail_end = phys_avail[i+1]; + + virtual_avail = IA64_RR_BASE(5); + virtual_end = IA64_RR_BASE(6)-1; + + /* + * Initialize protection array. + */ + ia64_protection_init(); + + /* + * The kernel's pmap is statically allocated so we don't have to use + * pmap_create, which is unlikely to work correctly at this part of + * the boot sequence (XXX and which no longer exists). + */ + kernel_pmap = &kernel_pmap_store; + kernel_pmap->pm_count = 1; + kernel_pmap->pm_active = 1; + kernel_pmap->pm_asn = 0; + kernel_pmap->pm_asngen = pmap_current_asngen; + pmap_nextasn = 1; + TAILQ_INIT(&kernel_pmap->pm_pvlist); + + /* + * Region 5 is mapped via the vhpt. + */ + ia64_set_rr(IA64_RR_BASE(5), + (5 << 8) | (PAGE_SHIFT << 2) | 1); + + /* + * Region 6 is direct mapped UC and region 7 is direct mapped + * WC. The details of this is controlled by the Alt {I,D}TLB + * handlers. Here we just make sure that they have the largest + * possible page size to minimise TLB usage. + */ +#if 0 + ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (28 << 2)); + ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2)); +#endif + + /* + * We need some PVs to cope with pmap_kenter() calls prior to + * pmap_init(). This is all a bit flaky and needs to be + * rethought, probably by avoiding the zone allocator + * entirely. + */ + boot_pvs = 32768; + pvbootzone = &pvbootzone_store; + pvbootinit = (struct pv_entry *) + pmap_steal_memory(boot_pvs * sizeof (struct pv_entry)); + zbootinit(pvbootzone, "PV ENTRY", sizeof (struct pv_entry), + pvbootinit, boot_pvs); + + /* + * Set up proc0's PCB. + */ +#if 0 + proc0.p_addr->u_pcb.pcb_hw.apcb_asn = 0; +#endif +} + +/* + * Initialize the pmap module. + * Called by vm_init, to initialize any structures that the pmap + * system needs to map virtual memory. + * pmap_init has been enhanced to support in a fairly consistant + * way, discontiguous physical memory. + */ +void +pmap_init(phys_start, phys_end) + vm_offset_t phys_start, phys_end; +{ + int i; + int initial_pvs; + + /* + * Allocate memory for random pmap data structures. Includes the + * pv_head_table. + */ + + for(i = 0; i < vm_page_array_size; i++) { + vm_page_t m; + + m = &vm_page_array[i]; + TAILQ_INIT(&m->md.pv_list); + m->md.pv_list_count = 0; + } + + /* + * init the pv free list + */ + initial_pvs = vm_page_array_size; + if (initial_pvs < MINPV) + initial_pvs = MINPV; + pvzone = &pvzone_store; + pvinit = (struct pv_entry *) kmem_alloc(kernel_map, + initial_pvs * sizeof (struct pv_entry)); + zbootinit(pvzone, "PV ENTRY", sizeof (struct pv_entry), pvinit, + vm_page_array_size); + + /* + * Now it is safe to enable pv_table recording. + */ + pmap_initialized = TRUE; +} + +/* + * Initialize the address space (zone) for the pv_entries. Set a + * high water mark so that the system can recover from excessive + * numbers of pv entries. + */ +void +pmap_init2() +{ + pv_entry_max = PMAP_SHPGPERPROC * maxproc + vm_page_array_size; + pv_entry_high_water = 9 * (pv_entry_max / 10); + zinitna(pvzone, &pvzone_obj, NULL, 0, pv_entry_max, ZONE_INTERRUPT, 1); +} + + +/*************************************************** + * Manipulate TLBs for a pmap + ***************************************************/ + +static void +pmap_invalidate_asn(pmap_t pmap) +{ + pmap->pm_asngen = 0; +} + +static void +pmap_invalidate_page(pmap_t pmap, vm_offset_t va) +{ +#if 0 + if (pmap_isactive(pmap)) { + IA64_TBIS(va); + ia64_pal_imb(); /* XXX overkill? */ + } else + pmap_invalidate_asn(pmap); +#endif +} + +static void +pmap_invalidate_all(pmap_t pmap) +{ +#if 0 + if (pmap_isactive(pmap)) { + IA64_TBIA(); + ia64_pal_imb(); /* XXX overkill? */ + } else + pmap_invalidate_asn(pmap); +#endif +} + +static void +pmap_get_asn(pmap_t pmap) +{ +#if 0 + if (pmap->pm_asngen != pmap_current_asngen) { + if (pmap_nextasn > pmap_maxasn) { + /* + * Start a new ASN generation. + * + * Invalidate all per-process mappings and I-cache + */ + pmap_nextasn = 0; + pmap_current_asngen++; + + if (pmap_current_asngen == 0) { + /* + * Clear the pm_asngen of all pmaps. + * This is safe since it is only called from + * pmap_activate after it has deactivated + * the old pmap. + */ + struct proc *p; + pmap_t tpmap; + +#ifdef PMAP_DIAGNOSTIC + printf("pmap_get_asn: generation rollover\n"); +#endif + pmap_current_asngen = 1; + LIST_FOREACH(p, &allproc, p_list) { + if (p->p_vmspace) { + tpmap = vmspace_pmap(p->p_vmspace); + tpmap->pm_asngen = 0; + } + } + } + + /* + * Since we are about to start re-using ASNs, we must + * clear out the TLB and the I-cache since they are tagged + * with the ASN. + */ + IA64_TBIAP(); + ia64_pal_imb(); /* XXX overkill? */ + } + pmap->pm_asn = pmap_nextasn++; + pmap->pm_asngen = pmap_current_asngen; + } +#endif +} + +/*************************************************** + * Low level helper routines..... + ***************************************************/ + +/* + * Install a pte into the VHPT + */ +static PMAP_INLINE void +pmap_install_pte(struct ia64_lpte *vhpte, struct ia64_lpte *pte) +{ + u_int64_t *vhp, *p; + + /* invalidate the pte */ + atomic_set_64(&vhpte->pte_tag, 1L << 63); + ia64_mf(); /* make sure everyone sees */ + + vhp = (u_int64_t *) vhpte; + p = (u_int64_t *) pte; + + vhp[0] = p[0]; + vhp[1] = p[1]; + vhp[2] = p[2]; /* sets ti to one */ + + ia64_mf(); +} + +/* + * Compare essential parts of pte. + */ +static PMAP_INLINE int +pmap_equal_pte(struct ia64_lpte *pte1, struct ia64_lpte *pte2) +{ + return *(u_int64_t *) pte1 == *(u_int64_t *) pte2; +} + +/* + * this routine defines the region(s) of memory that should + * not be tested for the modified bit. + */ +static PMAP_INLINE int +pmap_track_modified(vm_offset_t va) +{ + if ((va < clean_sva) || (va >= clean_eva)) + return 1; + else + return 0; +} + +/* + * Create the UPAGES for a new process. + * This routine directly affects the fork perf for a process. + */ +void +pmap_new_proc(struct proc *p) +{ + int i; + vm_object_t upobj; + vm_page_t m; + struct user *up; + + /* + * allocate object for the upages + */ + if ((upobj = p->p_upages_obj) == NULL) { + upobj = vm_object_allocate( OBJT_DEFAULT, UPAGES); + p->p_upages_obj = upobj; + } + + /* get a kernel virtual address for the UPAGES for this proc */ + if ((up = p->p_addr) == NULL) { + up = (struct user *) kmem_alloc_nofault(kernel_map, + UPAGES * PAGE_SIZE); + if (up == NULL) + panic("pmap_new_proc: u_map allocation failed"); + p->p_addr = up; + } + + for(i=0;i<UPAGES;i++) { + /* + * Get a kernel stack page + */ + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + + /* + * Wire the page + */ + m->wire_count++; + cnt.v_wire_count++; + + pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE, + VM_PAGE_TO_PHYS(m)); + + pmap_invalidate_page(kernel_pmap, + (vm_offset_t)up + i * PAGE_SIZE); + + vm_page_wakeup(m); + vm_page_flag_clear(m, PG_ZERO); + vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE); + m->valid = VM_PAGE_BITS_ALL; + } +} + +/* + * Dispose the UPAGES for a process that has exited. + * This routine directly impacts the exit perf of a process. + */ +void +pmap_dispose_proc(p) + struct proc *p; +{ + int i; + vm_object_t upobj; + vm_page_t m; + + upobj = p->p_upages_obj; + + for(i=0;i<UPAGES;i++) { + + if ((m = vm_page_lookup(upobj, i)) == NULL) + panic("pmap_dispose_proc: upage already missing???"); + + vm_page_busy(m); + + pmap_kremove((vm_offset_t)p->p_addr + PAGE_SIZE * i); + + vm_page_unwire(m, 0); + vm_page_free(m); + } +} + +/* + * Allow the UPAGES for a process to be prejudicially paged out. + */ +void +pmap_swapout_proc(p) + struct proc *p; +{ + int i; + vm_object_t upobj; + vm_page_t m; + + /* + * Make sure we aren't fpcurproc. + */ + ia64_fpstate_save(p, 1); + + upobj = p->p_upages_obj; + /* + * let the upages be paged + */ + for(i=0;i<UPAGES;i++) { + if ((m = vm_page_lookup(upobj, i)) == NULL) + panic("pmap_swapout_proc: upage already missing???"); + vm_page_dirty(m); + vm_page_unwire(m, 0); + pmap_kremove((vm_offset_t)p->p_addr + PAGE_SIZE * i); + } +} + +/* + * Bring the UPAGES for a specified process back in. + */ +void +pmap_swapin_proc(p) + struct proc *p; +{ + int i,rv; + vm_object_t upobj; + vm_page_t m; + + upobj = p->p_upages_obj; + for(i=0;i<UPAGES;i++) { + + m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); + + pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE, + VM_PAGE_TO_PHYS(m)); + + if (m->valid != VM_PAGE_BITS_ALL) { + rv = vm_pager_get_pages(upobj, &m, 1, 0); + if (rv != VM_PAGER_OK) + panic("pmap_swapin_proc: cannot get upages for proc: %d\n", p->p_pid); + m = vm_page_lookup(upobj, i); + m->valid = VM_PAGE_BITS_ALL; + } + + vm_page_wire(m); + vm_page_wakeup(m); + vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE); + } + + /* + * The pcb may be at a different physical address now so cache the + * new address. + */ + p->p_md.md_pcbpaddr = (void*) vtophys((vm_offset_t) &p->p_addr->u_pcb); +} + +/*************************************************** + * Page table page management routines..... + ***************************************************/ + +void +pmap_pinit0(pmap) + struct pmap *pmap; +{ + /* + * kernel_pmap is the same as any other pmap. + */ + pmap_pinit(pmap); + pmap->pm_flags = 0; + pmap->pm_count = 1; + pmap->pm_ptphint = NULL; + pmap->pm_active = 0; + pmap->pm_asn = 0; + pmap->pm_asngen = 0; + TAILQ_INIT(&pmap->pm_pvlist); + bzero(&pmap->pm_stats, sizeof pmap->pm_stats); +} + +/* + * Initialize a preallocated and zeroed pmap structure, + * such as one in a vmspace structure. + */ +void +pmap_pinit(pmap) + register struct pmap *pmap; +{ + pmap->pm_flags = 0; + pmap->pm_count = 1; + pmap->pm_ptphint = NULL; + pmap->pm_active = 0; + pmap->pm_asn = 0; + pmap->pm_asngen = 0; + TAILQ_INIT(&pmap->pm_pvlist); + bzero(&pmap->pm_stats, sizeof pmap->pm_stats); +} + +/* + * Wire in kernel global address entries. To avoid a race condition + * between pmap initialization and pmap_growkernel, this procedure + * should be called after the vmspace is attached to the process + * but before this pmap is activated. + */ +void +pmap_pinit2(pmap) + struct pmap *pmap; +{ +} + +/*************************************************** +* Pmap allocation/deallocation routines. + ***************************************************/ + +/* + * Release any resources held by the given physical map. + * Called when a pmap initialized by pmap_pinit is being released. + * Should only be called if the map contains no valid mappings. + */ +void +pmap_release(pmap_t pmap) +{ +#if defined(DIAGNOSTIC) + if (object->ref_count != 1) + panic("pmap_release: pteobj reference count != 1"); +#endif +} + +/* + * grow the number of kernel page table entries, if needed + */ +void +pmap_growkernel(vm_offset_t addr) +{ +} + +/* + * Retire the given physical map from service. + * Should only be called if the map contains + * no valid mappings. + */ +void +pmap_destroy(pmap_t pmap) +{ + int count; + + if (pmap == NULL) + return; + + count = --pmap->pm_count; + if (count == 0) { + pmap_release(pmap); + panic("destroying a pmap is not yet implemented"); + } +} + +/* + * Add a reference to the specified pmap. + */ +void +pmap_reference(pmap_t pmap) +{ + if (pmap != NULL) { + pmap->pm_count++; + } +} + +/*************************************************** +* page management routines. + ***************************************************/ + +/* + * free the pv_entry back to the free list + */ +static PMAP_INLINE void +free_pv_entry(pv_entry_t pv) +{ + pv_entry_count--; + zfreei(pvzone, pv); +} + +/* + * get a new pv_entry, allocating a block from the system + * when needed. + * the memory allocation is performed bypassing the malloc code + * because of the possibility of allocations at interrupt time. + */ +static pv_entry_t +get_pv_entry(void) +{ + if (!pvinit) + return zalloci(pvbootzone); + + pv_entry_count++; + if (pv_entry_high_water && + (pv_entry_count > pv_entry_high_water) && + (pmap_pagedaemon_waken == 0)) { + pmap_pagedaemon_waken = 1; + wakeup (&vm_pages_needed); + } + return zalloci(pvzone); +} + +/* + * Add a pv_entry to the VHPT. + */ +static void +pmap_enter_vhpt(pv_entry_t pv) +{ + struct ia64_lpte *vhpte; + + vhpte = (struct ia64_lpte *) ia64_thash(pv->pv_va); + + pv->pv_pte.pte_chain = vhpte->pte_chain; + vhpte->pte_chain = ia64_tpa((vm_offset_t) pv); + + if (!vhpte->pte_p && pv->pv_pte.pte_p) + pmap_install_pte(vhpte, &pv->pv_pte); + else + ia64_mf(); +} + +/* + * Update VHPT after pv->pv_pte has changed. + */ +static void +pmap_update_vhpt(pv_entry_t pv) +{ + struct ia64_lpte *vhpte; + + vhpte = (struct ia64_lpte *) ia64_thash(pv->pv_va); + + if ((!vhpte->pte_p || vhpte->pte_tag == pv->pv_pte.pte_tag) + && pv->pv_pte.pte_p) + pmap_install_pte(vhpte, &pv->pv_pte); +} + +/* + * Remove a pv_entry from the VHPT. Return true if it worked. + */ +static int +pmap_remove_vhpt(pv_entry_t pv) +{ + struct ia64_lpte *pte; + struct ia64_lpte *lpte; + struct ia64_lpte *vhpte; + u_int64_t tag; + + vhpte = (struct ia64_lpte *) ia64_thash(pv->pv_va); + + /* + * If the VHPTE is invalid, there can't be a collision chain. + */ + if (!vhpte->pte_p) + return 1; + + lpte = vhpte; + pte = (struct ia64_lpte *) IA64_PHYS_TO_RR7(vhpte->pte_chain); + tag = ia64_ttag(pv->pv_va); + + while (pte->pte_tag != tag) { + lpte = pte; + if (pte->pte_chain) + pte = (struct ia64_lpte *) IA64_PHYS_TO_RR7(pte->pte_chain); + else + return 1; /* error here? */ + } + + /* + * Snip this pv_entry out of the collision chain. + */ + lpte->pte_chain = pte->pte_chain; + + /* + * If the VHPTE matches as well, change it to map the first + * element from the chain if there is one. + */ + if (vhpte->pte_tag == tag) { + if (vhpte->pte_chain) { + pte = (struct ia64_lpte *) + IA64_PHYS_TO_RR7(vhpte->pte_chain); + pmap_install_pte(vhpte, pte); + } else { + vhpte->pte_p = 0; + ia64_mf(); + } + } + + return 0; +} + +/* + * Make a pv_entry_t which maps the given virtual address. The pte + * will be initialised with pte_p = 0. The function pmap_set_pv() + * should be called to change the value of the pte. + * Must be called at splvm(). + */ +static pv_entry_t +pmap_make_pv(pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + + pv = get_pv_entry(); + bzero(pv, sizeof(*pv)); + pv->pv_va = va; + pv->pv_pmap = pmap; + + pv->pv_pte.pte_p = 0; /* invalid for now */ + pv->pv_pte.pte_ma = PTE_MA_WB; /* cacheable, write-back */ + pv->pv_pte.pte_a = 0; + pv->pv_pte.pte_d = 0; + pv->pv_pte.pte_pl = 0; /* privilege level 0 */ + pv->pv_pte.pte_ar = 3; /* read/write/execute */ + pv->pv_pte.pte_ppn = 0; /* physical address */ + pv->pv_pte.pte_ed = 0; + pv->pv_pte.pte_ig = 0; + + pv->pv_pte.pte_ps = PAGE_SHIFT; /* page size */ + pv->pv_pte.pte_key = 0; /* protection key */ + + pv->pv_pte.pte_tag = ia64_ttag(va); + + pmap_enter_vhpt(pv); + + TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist); + pmap->pm_stats.resident_count++; + + return pv; +} + +/* + * Initialise a pv_entry_t with a given physical address and + * protection code. If the passed vm_page_t is non-zero, the entry is + * added to its list of mappings. + * Must be called at splvm(). + */ +static void +pmap_set_pv(pmap_t pmap, pv_entry_t pv, vm_offset_t pa, + int prot, vm_page_t m) +{ + if (pv->pv_pte.pte_p && pv->pv_pte.pte_ig & PTE_IG_MANAGED) { + vm_offset_t opa = pv->pv_pte.pte_ppn << 12; + vm_page_t om = PHYS_TO_VM_PAGE(opa); + + TAILQ_REMOVE(&om->md.pv_list, pv, pv_list); + om->md.pv_list_count--; + + if (TAILQ_FIRST(&om->md.pv_list) == NULL) + vm_page_flag_clear(om, PG_MAPPED | PG_WRITEABLE); + } + + pv->pv_pte.pte_p = 1; /* set to valid */ + if (m) { + pv->pv_pte.pte_a = 0; + pv->pv_pte.pte_d = 0; + } else { + pv->pv_pte.pte_a = 1; + pv->pv_pte.pte_d = 1; + } + pv->pv_pte.pte_a = 1; /* XXX remove this after implementing trap */ + pv->pv_pte.pte_d = 1; + pv->pv_pte.pte_pl = prot & 3; /* privilege level 0 */ + pv->pv_pte.pte_ar = prot >> 2; /* read/write/execute */ + pv->pv_pte.pte_ppn = pa >> 12; /* physical address */ + + if (m) { + pv->pv_pte.pte_ig |= PTE_IG_MANAGED; + TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list); + m->md.pv_list_count++; + } + + /* + * Update the VHPT entry if it needs to change. + */ + pmap_update_vhpt(pv); +} + +/* + * Remove a mapping represented by a particular pv_entry_t. If the + * passed vm_page_t is non-zero, then the entry is removed from it. + * Must be called at splvm(). + */ +static int +pmap_remove_pv(pmap_t pmap, pv_entry_t pv, vm_page_t m) +{ + int rtval; + + /* + * First remove from the VHPT. + */ + rtval = pmap_remove_vhpt(pv); + if (!rtval) + return rtval; + + if (m) { + TAILQ_REMOVE(&m->md.pv_list, pv, pv_list); + m->md.pv_list_count--; + + if (TAILQ_FIRST(&m->md.pv_list) == NULL) + vm_page_flag_clear(m, PG_MAPPED | PG_WRITEABLE); + } + + TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist); + pmap->pm_stats.resident_count--; + + free_pv_entry(pv); + + return (rtval); +} + +/* + * Find a pv given a pmap and virtual address. + */ +static pv_entry_t +pmap_find_pv(pmap_t pmap, vm_offset_t va) +{ + struct ia64_lpte *pte; + u_int64_t tag; + + pte = (struct ia64_lpte *) ia64_thash(va); + if (!pte->pte_chain) + return 0; + + tag = ia64_ttag(va); + pte = (struct ia64_lpte *) IA64_PHYS_TO_RR7(pte->pte_chain); + + while (pte->pte_tag != tag) { + if (pte->pte_chain) + pte = (struct ia64_lpte *) IA64_PHYS_TO_RR7(pte->pte_chain); + else + return 0; + } + + return (pv_entry_t) pte; /* XXX wrong va */ +} + +/* + * Routine: pmap_extract + * Function: + * Extract the physical page address associated + * with the given map/virtual_address pair. + */ +vm_offset_t +pmap_extract(pmap, va) + register pmap_t pmap; + vm_offset_t va; +{ + pv_entry_t pv = pmap_find_pv(pmap, va); + if (pv) + return pmap_pte_pa(&pv->pv_pte); + else + return 0; +} + +/*************************************************** + * Low level mapping routines..... + ***************************************************/ + +/* + * Add a list of wired pages to the kva + * this routine is only used for temporary + * kernel mappings that do not need to have + * page modification or references recorded. + * Note that old mappings are simply written + * over. The page *must* be wired. + */ +void +pmap_qenter(vm_offset_t va, vm_page_t *m, int count) +{ + int i, inval; + pv_entry_t pv; + + for (i = 0; i < count; i++) { + vm_offset_t tva = va + i * PAGE_SIZE; + pv = pmap_find_pv(kernel_pmap, tva); + inval = 0; + if (!pv) + pv = pmap_make_pv(kernel_pmap, tva); + else + inval = 1; + + PMAP_DEBUG_VA(va); + pmap_set_pv(kernel_pmap, pv, + VM_PAGE_TO_PHYS(m[i]), + (PTE_AR_RWX<<2) | PTE_PL_KERN, 0); + if (inval) + pmap_invalidate_page(kernel_pmap, tva); + } +} + +/* + * this routine jerks page mappings from the + * kernel -- it is meant only for temporary mappings. + */ +void +pmap_qremove(va, count) + vm_offset_t va; + int count; +{ + int i; + pv_entry_t pv; + + for (i = 0; i < count; i++) { + pv = pmap_find_pv(kernel_pmap, va); + PMAP_DEBUG_VA(va); + if (pv) { + pmap_remove_pv(kernel_pmap, pv, 0); + pmap_invalidate_page(kernel_pmap, va); + } + va += PAGE_SIZE; + } +} + +/* + * Add a wired page to the kva. + */ +void +pmap_kenter(vm_offset_t va, vm_offset_t pa) +{ + pv_entry_t pv; + + pv = pmap_find_pv(kernel_pmap, va); + if (!pv) + pv = pmap_make_pv(kernel_pmap, va); + pmap_set_pv(kernel_pmap, pv, + pa, (PTE_AR_RWX<<2) | PTE_PL_KERN, 0); +} + +/* + * Remove a page from the kva + */ +void +pmap_kremove(vm_offset_t va) +{ + pv_entry_t pv; + + pv = pmap_find_pv(kernel_pmap, va); + if (pv) + pmap_remove_pv(kernel_pmap, pv, 0); +} + +/* + * Used to map a range of physical addresses into kernel + * virtual address space. + * + * For now, VM is already on, we only need to map the + * specified memory. + */ +vm_offset_t +pmap_map(vm_offset_t virt, vm_offset_t start, vm_offset_t end, int prot) +{ + /* + * XXX We should really try to use larger pagesizes here to + * cut down the number of PVs used. + */ + while (start < end) { + pmap_kenter(virt, start); + virt += PAGE_SIZE; + start += PAGE_SIZE; + } + return (virt); +} + +/* + * This routine is very drastic, but can save the system + * in a pinch. + */ +void +pmap_collect() +{ + int i; + vm_page_t m; + static int warningdone=0; + + if (pmap_pagedaemon_waken == 0) + return; + + if (warningdone < 5) { + printf("pmap_collect: collecting pv entries -- suggest increasing PMAP_SHPGPERPROC\n"); + warningdone++; + } + + for(i = 0; i < vm_page_array_size; i++) { + m = &vm_page_array[i]; + if (m->wire_count || m->hold_count || m->busy || + (m->flags & PG_BUSY)) + continue; + pmap_remove_all(m); + } + pmap_pagedaemon_waken = 0; +} + +/* + * Remove a single page from a process address space + */ +static void +pmap_remove_page(pmap_t pmap, vm_offset_t va) +{ + pv_entry_t pv; + vm_page_t m; + int rtval; + int s; + + s = splvm(); + + pv = pmap_find_pv(pmap, va); + + rtval = 0; + if (pv) { + m = PHYS_TO_VM_PAGE(pmap_pte_pa(&pv->pv_pte)); + rtval = pmap_remove_pv(pmap, pv, m); + } + + splx(s); + return; +} + +/* + * Remove the given range of addresses from the specified map. + * + * It is assumed that the start and end are properly + * rounded to the page size. + */ +void +pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + vm_offset_t va, nva; + + if (pmap == NULL) + return; + + if (pmap->pm_stats.resident_count == 0) + return; + + /* + * special handling of removing one page. a very + * common operation and easy to short circuit some + * code. + */ + if (sva + PAGE_SIZE == eva) { + pmap_remove_page(pmap, sva); + return; + } + + if (atop(eva - sva) > pmap->pm_stats.resident_count) { + for (va = sva; va < eva; va = nva) { + pmap_remove_page(pmap, va); + nva = va + PAGE_SIZE; + } + } else { + pv_entry_t pv, pvnext; + int s; + + s = splvm(); + for (pv = TAILQ_FIRST(&pmap->pm_pvlist); + pv; + pv = pvnext) { + pvnext = TAILQ_NEXT(pv, pv_plist); + if (pv->pv_va >= sva && pv->pv_va < eva) { + vm_page_t m = PHYS_TO_VM_PAGE(pmap_pte_pa(&pv->pv_pte)); + pmap_remove_pv(pmap, pv, m); + } + } + splx(s); + } +} + +/* + * Routine: pmap_remove_all + * Function: + * Removes this physical page from + * all physical maps in which it resides. + * Reflects back modify bits to the pager. + * + * Notes: + * Original versions of this routine were very + * inefficient because they iteratively called + * pmap_remove (slow...) + */ + +static void +pmap_remove_all(vm_page_t m) +{ + register pv_entry_t pv; + int nmodify; + int s; + + nmodify = 0; +#if defined(PMAP_DIAGNOSTIC) + /* + * XXX this makes pmap_page_protect(NONE) illegal for non-managed + * pages! + */ + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) { + panic("pmap_page_protect: illegal for unmanaged page, va: 0x%lx", VM_PAGE_TO_PHYS(m)); + } +#endif + + s = splvm(); + + while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { + vm_page_t m = PHYS_TO_VM_PAGE(pmap_pte_pa(&pv->pv_pte)); + pmap_remove_pv(pv->pv_pmap, pv, m); + pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + } + + vm_page_flag_clear(m, PG_MAPPED | PG_WRITEABLE); + + splx(s); + return; +} + +/* + * Set the physical protection on the + * specified range of this map as requested. + */ +void +pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) +{ + pv_entry_t pv; + int newprot; + + if (pmap == NULL) + return; + + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + + if (prot & VM_PROT_WRITE) + return; + + newprot = pte_prot(pmap, prot); + + if ((sva & PAGE_MASK) || (eva & PAGE_MASK)) + panic("pmap_protect: unaligned addresses"); + + while (sva < eva) { + /* + * If page is invalid, skip this page + */ + pv = pmap_find_pv(pmap, sva); + if (!pv) { + sva += PAGE_SIZE; + continue; + } + + if (pmap_pte_prot(&pv->pv_pte) != newprot) { + pmap_pte_set_prot(&pv->pv_pte, newprot); + pmap_update_vhpt(pv); + pmap_invalidate_page(pmap, sva); + } + + sva += PAGE_SIZE; + } +} + +/* + * Insert the given physical page (p) at + * the specified virtual address (v) in the + * target physical map with the protection requested. + * + * If specified, the page will be wired down, meaning + * that the related pte can not be reclaimed. + * + * NB: This is the only routine which MAY NOT lazy-evaluate + * or lose information. That is, this routine must actually + * insert this page into the given map NOW. + */ +void +pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, + boolean_t wired) +{ + vm_offset_t pa; + pv_entry_t pv; + vm_offset_t opa; + struct ia64_lpte origpte; + int managed; + + if (pmap == NULL) + return; + + va &= ~PAGE_MASK; +#ifdef PMAP_DIAGNOSTIC + if (va > VM_MAX_KERNEL_ADDRESS) + panic("pmap_enter: toobig"); +#endif + + pv = pmap_find_pv(pmap, va); + if (!pv) + pv = pmap_make_pv(pmap, va); + + origpte = pv->pv_pte; + if (origpte.pte_p) + opa = pmap_pte_pa(&origpte); + else + opa = 0; + + pa = VM_PAGE_TO_PHYS(m) & ~PAGE_MASK; + managed = 0; + + /* + * Mapping has not changed, must be protection or wiring change. + */ + if (origpte.pte_p && (opa == pa)) { + /* + * Wiring change, just update stats. We don't worry about + * wiring PT pages as they remain resident as long as there + * are valid mappings in them. Hence, if a user page is wired, + * the PT page will be also. + */ + if (wired && ((origpte.pte_ig & PTE_IG_WIRED) == 0)) + pmap->pm_stats.wired_count++; + else if (!wired && (origpte.pte_ig & PTE_IG_WIRED)) + pmap->pm_stats.wired_count--; + + managed = origpte.pte_ig & PTE_IG_MANAGED; + goto validate; + } else { + /* + * Mapping has changed, invalidate old range and fall + * through to handle validating new mapping. + */ + } + + /* + * Increment counters + */ + if (wired) + pmap->pm_stats.wired_count++; + +validate: + /* + * Now validate mapping with desired protection/wiring. + * This enters the pv_entry_t on the page's list if necessary. + */ + pmap_set_pv(pmap, pv, pa, pte_prot(pmap, prot), m); + + if (wired) + pv->pv_pte.pte_ig |= PTE_IG_WIRED; + + /* + * if the mapping or permission bits are different, we need + * to invalidate the page. + */ + if (pmap_equal_pte(&origpte, &pv->pv_pte)) { + PMAP_DEBUG_VA(va); + if (origpte.pte_p) + pmap_invalidate_page(pmap, va); + } +} + +/* + * this code makes some *MAJOR* assumptions: + * 1. Current pmap & pmap exists. + * 2. Not wired. + * 3. Read access. + * 4. No page table pages. + * 5. Tlbflush is deferred to calling procedure. + * 6. Page IS managed. + * but is *MUCH* faster than pmap_enter... + */ + +static void +pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m) +{ + pv_entry_t pv; + int s; + + s = splvm(); + + pv = pmap_find_pv(pmap, va); + if (!pv) + pv = pmap_make_pv(pmap, va); + + /* + * Enter on the PV list if part of our managed memory. Note that we + * raise IPL while manipulating pv_table since pmap_enter can be + * called at interrupt time. + */ + PMAP_DEBUG_VA(va); + pmap_set_pv(pmap, pv, VM_PAGE_TO_PHYS(m), + (PTE_AR_R << 2) | PTE_PL_USER, m); + + splx(s); +} + +/* + * Make temporary mapping for a physical address. This is called + * during dump. + */ +void * +pmap_kenter_temporary(vm_offset_t pa) +{ + return (void *) IA64_PHYS_TO_RR7(pa); +} + +#define MAX_INIT_PT (96) +/* + * pmap_object_init_pt preloads the ptes for a given object + * into the specified pmap. This eliminates the blast of soft + * faults on process startup and immediately after an mmap. + */ +void +pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, + vm_object_t object, vm_pindex_t pindex, + vm_size_t size, int limit) +{ + vm_offset_t tmpidx; + int psize; + vm_page_t p; + int objpgs; + + if (pmap == NULL || object == NULL) + return; + + psize = ia64_btop(size); + + if ((object->type != OBJT_VNODE) || + (limit && (psize > MAX_INIT_PT) && + (object->resident_page_count > MAX_INIT_PT))) { + return; + } + + if (psize + pindex > object->size) + psize = object->size - pindex; + + /* + * if we are processing a major portion of the object, then scan the + * entire thing. + */ + if (psize > (object->resident_page_count >> 2)) { + objpgs = psize; + + for (p = TAILQ_FIRST(&object->memq); + ((objpgs > 0) && (p != NULL)); + p = TAILQ_NEXT(p, listq)) { + + tmpidx = p->pindex; + if (tmpidx < pindex) { + continue; + } + tmpidx -= pindex; + if (tmpidx >= psize) { + continue; + } + if (((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && + (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { + if ((p->queue - p->pc) == PQ_CACHE) + vm_page_deactivate(p); + vm_page_busy(p); + pmap_enter_quick(pmap, + addr + ia64_ptob(tmpidx), p); + vm_page_flag_set(p, PG_MAPPED); + vm_page_wakeup(p); + } + objpgs -= 1; + } + } else { + /* + * else lookup the pages one-by-one. + */ + for (tmpidx = 0; tmpidx < psize; tmpidx += 1) { + p = vm_page_lookup(object, tmpidx + pindex); + if (p && + ((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && + (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { + if ((p->queue - p->pc) == PQ_CACHE) + vm_page_deactivate(p); + vm_page_busy(p); + pmap_enter_quick(pmap, + addr + ia64_ptob(tmpidx), p); + vm_page_flag_set(p, PG_MAPPED); + vm_page_wakeup(p); + } + } + } + return; +} + +/* + * pmap_prefault provides a quick way of clustering + * pagefaults into a processes address space. It is a "cousin" + * of pmap_object_init_pt, except it runs at page fault time instead + * of mmap time. + */ +#define PFBAK 4 +#define PFFOR 4 +#define PAGEORDER_SIZE (PFBAK+PFFOR) + +static int pmap_prefault_pageorder[] = { + -PAGE_SIZE, PAGE_SIZE, + -2 * PAGE_SIZE, 2 * PAGE_SIZE, + -3 * PAGE_SIZE, 3 * PAGE_SIZE + -4 * PAGE_SIZE, 4 * PAGE_SIZE +}; + +void +pmap_prefault(pmap, addra, entry) + pmap_t pmap; + vm_offset_t addra; + vm_map_entry_t entry; +{ + int i; + vm_offset_t starta; + vm_offset_t addr; + vm_pindex_t pindex; + vm_page_t m, mpte; + vm_object_t object; + + if (!curproc || (pmap != vmspace_pmap(curproc->p_vmspace))) + return; + + object = entry->object.vm_object; + + starta = addra - PFBAK * PAGE_SIZE; + if (starta < entry->start) { + starta = entry->start; + } else if (starta > addra) { + starta = 0; + } + + mpte = NULL; + for (i = 0; i < PAGEORDER_SIZE; i++) { + vm_object_t lobject; + pv_entry_t pv; + + addr = addra + pmap_prefault_pageorder[i]; + if (addr > addra + (PFFOR * PAGE_SIZE)) + addr = 0; + + if (addr < starta || addr >= entry->end) + continue; + + pv = pmap_find_pv(pmap, addr); + if (pv) + continue; + + pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT; + lobject = object; + for (m = vm_page_lookup(lobject, pindex); + (!m && (lobject->type == OBJT_DEFAULT) && (lobject->backing_object)); + lobject = lobject->backing_object) { + if (lobject->backing_object_offset & PAGE_MASK) + break; + pindex += (lobject->backing_object_offset >> PAGE_SHIFT); + m = vm_page_lookup(lobject->backing_object, pindex); + } + + /* + * give-up when a page is not in memory + */ + if (m == NULL) + break; + + if (((m->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && + (m->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { + + if ((m->queue - m->pc) == PQ_CACHE) { + vm_page_deactivate(m); + } + vm_page_busy(m); + pmap_enter_quick(pmap, addr, m); + vm_page_flag_set(m, PG_MAPPED); + vm_page_wakeup(m); + } + } +} + +/* + * Routine: pmap_change_wiring + * Function: Change the wiring attribute for a map/virtual-address + * pair. + * In/out conditions: + * The mapping must already exist in the pmap. + */ +void +pmap_change_wiring(pmap, va, wired) + register pmap_t pmap; + vm_offset_t va; + boolean_t wired; +{ + pv_entry_t pv; + + if (pmap == NULL) + return; + + pv = pmap_find_pv(pmap, va); + + if (wired && !pmap_pte_w(&pv->pv_pte)) + pmap->pm_stats.wired_count++; + else if (!wired && pmap_pte_w(&pv->pv_pte)) + pmap->pm_stats.wired_count--; + + /* + * Wiring is not a hardware characteristic so there is no need to + * invalidate TLB. + */ + pmap_pte_set_w(&pv->pv_pte, wired); +} + + + +/* + * Copy the range specified by src_addr/len + * from the source map to the range dst_addr/len + * in the destination map. + * + * This routine is only advisory and need not do anything. + */ + +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) +{ +} + +/* + * Routine: pmap_kernel + * Function: + * Returns the physical map handle for the kernel. + */ +pmap_t +pmap_kernel() +{ + return (kernel_pmap); +} + +/* + * pmap_zero_page zeros the specified hardware page by + * mapping it into virtual memory and using bzero to clear + * its contents. + */ + +void +pmap_zero_page(vm_offset_t pa) +{ + vm_offset_t va = IA64_PHYS_TO_RR7(pa); + bzero((caddr_t) va, PAGE_SIZE); +} + + +/* + * pmap_zero_page_area zeros the specified hardware page by + * mapping it into virtual memory and using bzero to clear + * its contents. + * + * off and size must reside within a single page. + */ + +void +pmap_zero_page_area(vm_offset_t pa, int off, int size) +{ + vm_offset_t va = IA64_PHYS_TO_RR7(pa); + bzero((char *)(caddr_t)va + off, size); +} + +/* + * pmap_copy_page copies the specified (machine independent) + * page by mapping the page into virtual memory and using + * bcopy to copy the page, one machine dependent page at a + * time. + */ +void +pmap_copy_page(vm_offset_t src, vm_offset_t dst) +{ + src = IA64_PHYS_TO_RR7(src); + dst = IA64_PHYS_TO_RR7(dst); + bcopy((caddr_t) src, (caddr_t) dst, PAGE_SIZE); +} + + +/* + * Routine: pmap_pageable + * Function: + * Make the specified pages (by pmap, offset) + * pageable (or not) as requested. + * + * A page which is not pageable may not take + * a fault; therefore, its page table entry + * must remain valid for the duration. + * + * This routine is merely advisory; pmap_enter + * will specify that these pages are to be wired + * down (or not) as appropriate. + */ +void +pmap_pageable(pmap, sva, eva, pageable) + pmap_t pmap; + vm_offset_t sva, eva; + boolean_t pageable; +{ +} + +/* + * this routine returns true if a physical page resides + * in the given pmap. + */ +boolean_t +pmap_page_exists(pmap, m) + pmap_t pmap; + vm_page_t m; +{ + register pv_entry_t pv; + int s; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return FALSE; + + s = splvm(); + + /* + * Not found, check current mappings returning immediately if found. + */ + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pmap == pmap) { + splx(s); + return TRUE; + } + } + splx(s); + return (FALSE); +} + +#define PMAP_REMOVE_PAGES_CURPROC_ONLY +/* + * Remove all pages from specified address space + * this aids process exit speeds. Also, this code + * is special cased for current process only, but + * can have the more generic (and slightly slower) + * mode enabled. This is much faster than pmap_remove + * in the case of running down an entire address space. + */ +void +pmap_remove_pages(pmap, sva, eva) + pmap_t pmap; + vm_offset_t sva, eva; +{ + pv_entry_t pv, npv; + int s; + +#ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY + if (!curproc || (pmap != vmspace_pmap(curproc->p_vmspace))) { + printf("warning: pmap_remove_pages called with non-current pmap\n"); + return; + } +#endif + + s = splvm(); + for (pv = TAILQ_FIRST(&pmap->pm_pvlist); + pv; + pv = npv) { + vm_page_t m; + + npv = TAILQ_NEXT(pv, pv_plist); + + if (pv->pv_va >= eva || pv->pv_va < sva) { + continue; + } + +/* + * We cannot remove wired pages from a process' mapping at this time + */ + if (pv->pv_pte.pte_ig & PTE_IG_WIRED) { + continue; + } + + PMAP_DEBUG_VA(pv->pv_va); + + m = PHYS_TO_VM_PAGE(pmap_pte_pa(&pv->pv_pte)); + pmap_remove_pv(pmap, pv, m); + } + splx(s); + + pmap_invalidate_all(pmap); +} + +/* + * this routine is used to modify bits in ptes + */ +static void +pmap_changebit(vm_page_t m, int bit, boolean_t setem) +{ +#if 0 + pv_entry_t pv; + int changed; + int s; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return; + + s = splvm(); + changed = 0; + + /* + * Loop over all current mappings setting/clearing as appropos If + * setting RO do we need to clear the VAC? + */ + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + + /* + * don't write protect pager mappings + */ + if (!setem && bit == (PG_UWE|PG_KWE)) { + if (!pmap_track_modified(pv->pv_va)) + continue; + } + +#if defined(PMAP_DIAGNOSTIC) + if (!pv->pv_pmap) { + printf("Null pmap (cb) at va: 0x%lx\n", pv->pv_va); + continue; + } +#endif + + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + + changed = 0; + if (setem) { + *pte |= bit; + changed = 1; + } else { + pt_entry_t pbits = *pte; + if (pbits & bit) { + changed = 1; + *pte = pbits & ~bit; + } + } + if (changed) + pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + } + splx(s); +#endif +} + +/* + * pmap_page_protect: + * + * Lower the permission for all mappings to a given page. + */ +void +pmap_page_protect(vm_page_t m, vm_prot_t prot) +{ +#if 0 + if ((prot & VM_PROT_WRITE) == 0) { + if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { + pmap_changebit(m, PG_KWE|PG_UWE, FALSE); + } else { + pmap_remove_all(m); + } + } +#endif +} + +vm_offset_t +pmap_phys_address(ppn) + int ppn; +{ + return (ia64_ptob(ppn)); +} + +/* + * pmap_ts_referenced: + * + * Return the count of reference bits for a page, clearing all of them. + * + */ +int +pmap_ts_referenced(vm_page_t m) +{ + pv_entry_t pv; + int count = 0; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return 0; + + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pte.pte_a) { + count++; + pv->pv_pte.pte_a = 0; + pmap_update_vhpt(pv); + } + } + + return count; +} + +/* + * pmap_is_referenced: + * + * Return whether or not the specified physical page was referenced + * in any physical maps. + */ +static boolean_t +pmap_is_referenced(vm_page_t m) +{ + pv_entry_t pv; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return FALSE; + + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pte.pte_a) { + return 1; + } + } + + return 0; +} + +/* + * pmap_is_modified: + * + * Return whether or not the specified physical page was modified + * in any physical maps. + */ +boolean_t +pmap_is_modified(vm_page_t m) +{ + pv_entry_t pv; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return FALSE; + + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pte.pte_d) { + return 1; + } + } + + return 0; +} + +/* + * Clear the modify bits on the specified physical page. + */ +void +pmap_clear_modify(vm_page_t m) +{ + pv_entry_t pv; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return; + + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pte.pte_d) { + pv->pv_pte.pte_d = 0; + pmap_update_vhpt(pv); + } + } +} + +/* + * pmap_clear_reference: + * + * Clear the reference bit on the specified physical page. + */ +void +pmap_clear_reference(vm_page_t m) +{ + pv_entry_t pv; + + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) + return; + + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + if (pv->pv_pte.pte_a) { + pv->pv_pte.pte_a = 0; + pmap_update_vhpt(pv); + } + } +} + +/* + * Miscellaneous support routines follow + */ + +static void +ia64_protection_init() +{ + int prot, *kp, *up; + + kp = protection_codes[0]; + up = protection_codes[1]; + + for (prot = 0; prot < 8; prot++) { + switch (prot) { + case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE: + *kp++ = (PTE_AR_R << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_R << 2) | PTE_PL_KERN; + break; + + case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE: + *kp++ = (PTE_AR_X_RX << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_X_RX << 2) | PTE_PL_USER; + break; + + case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE: + *kp++ = (PTE_AR_RW << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_RW << 2) | PTE_PL_USER; + break; + + case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE: + *kp++ = (PTE_AR_RWX << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_RWX << 2) | PTE_PL_USER; + break; + + case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE: + *kp++ = (PTE_AR_R << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_R << 2) | PTE_PL_USER; + break; + + case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE: + *kp++ = (PTE_AR_RX << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_RX << 2) | PTE_PL_USER; + break; + + case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE: + *kp++ = (PTE_AR_RW << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_RW << 2) | PTE_PL_USER; + break; + + case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: + *kp++ = (PTE_AR_RWX << 2) | PTE_PL_KERN; + *up++ = (PTE_AR_RWX << 2) | PTE_PL_USER; + break; + } + } +} + +/* + * 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 * +pmap_mapdev(pa, size) + vm_offset_t pa; + vm_size_t size; +{ + return (void*) IA64_PHYS_TO_RR6(pa); +} + +/* + * perform the pmap work for mincore + */ +int +pmap_mincore(pmap, addr) + pmap_t pmap; + vm_offset_t addr; +{ + pv_entry_t pv; + struct ia64_lpte *pte; + int val = 0; + + pv = pmap_find_pv(pmap, addr); + if (pv == 0) { + return 0; + } + pte = &pv->pv_pte; + + if (pmap_pte_v(pte)) { + vm_page_t m; + vm_offset_t pa; + + val = MINCORE_INCORE; + if ((pte->pte_ig & PTE_IG_MANAGED) == 0) + return val; + + pa = pmap_pte_pa(pte); + + m = PHYS_TO_VM_PAGE(pa); + + /* + * Modified by us + */ + if (pte->pte_d) + val |= MINCORE_MODIFIED|MINCORE_MODIFIED_OTHER; + /* + * Modified by someone + */ + else if (pmap_is_modified(m)) + val |= MINCORE_MODIFIED_OTHER; + /* + * Referenced by us + */ + if (pte->pte_a) + val |= MINCORE_REFERENCED|MINCORE_REFERENCED_OTHER; + + /* + * Referenced by someone + */ + else if (pmap_ts_referenced(m)) { + val |= MINCORE_REFERENCED_OTHER; + vm_page_flag_set(m, PG_REFERENCED); + } + } + return val; +} + +void +pmap_activate(struct proc *p) +{ + pmap_t pmap; + + pmap = vmspace_pmap(p->p_vmspace); + + if (pmap_active && pmap != pmap_active) { + pmap_active->pm_active = 0; + pmap_active = 0; + } + + if (pmap->pm_asngen != pmap_current_asngen) + pmap_get_asn(pmap); + + pmap_active = pmap; + pmap->pm_active = 1; /* XXX use bitmap for SMP */ + +#if 0 + p->p_addr->u_pcb.pcb_hw.apcb_asn = pmap->pm_asn; +#endif + + if (p == curproc) { +#if 0 + ia64_pal_swpctx((u_long)p->p_md.md_pcbpaddr); +#endif + } +} + +void +pmap_deactivate(struct proc *p) +{ + pmap_t pmap; + pmap = vmspace_pmap(p->p_vmspace); + pmap->pm_active = 0; + pmap_active = 0; +} + +vm_offset_t +pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size) +{ + + return addr; +} + +#if 0 +#if defined(PMAP_DEBUG) +pmap_pid_dump(int pid) +{ + pmap_t pmap; + struct proc *p; + int npte = 0; + int index; + LIST_FOREACH(p, &allproc, p_list) { + if (p->p_pid != pid) + continue; + + if (p->p_vmspace) { + int i,j; + index = 0; + pmap = vmspace_pmap(p->p_vmspace); + for(i=0;i<1024;i++) { + pd_entry_t *pde; + pt_entry_t *pte; + unsigned base = i << PDRSHIFT; + + pde = &pmap->pm_pdir[i]; + if (pde && pmap_pde_v(pde)) { + for(j=0;j<1024;j++) { + unsigned va = base + (j << PAGE_SHIFT); + if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) { + if (index) { + index = 0; + printf("\n"); + } + return npte; + } + pte = pmap_pte_quick( pmap, va); + if (pte && pmap_pte_v(pte)) { + vm_offset_t pa; + vm_page_t m; + pa = *(int *)pte; + m = PHYS_TO_VM_PAGE(pa); + printf("va: 0x%x, pt: 0x%x, h: %d, w: %d, f: 0x%x", + va, pa, m->hold_count, m->wire_count, m->flags); + npte++; + index++; + if (index >= 2) { + index = 0; + printf("\n"); + } else { + printf(" "); + } + } + } + } + } + } + } + return npte; +} +#endif + +#if defined(DEBUG) + +static void pads __P((pmap_t pm)); +static void pmap_pvdump __P((vm_page_t m)); + +/* print address space of pmap*/ +static void +pads(pm) + pmap_t pm; +{ + int i, j; + vm_offset_t va; + pt_entry_t *ptep; + + if (pm == kernel_pmap) + return; + for (i = 0; i < 1024; i++) + if (pm->pm_pdir[i]) + for (j = 0; j < 1024; j++) { + va = (i << PDRSHIFT) + (j << PAGE_SHIFT); + if (pm == kernel_pmap && va < KERNBASE) + continue; + if (pm != kernel_pmap && va > UPT_MAX_ADDRESS) + continue; + ptep = pmap_pte_quick(pm, va); + if (pmap_pte_v(ptep)) + printf("%x:%x ", va, *(int *) ptep); + }; + +} + +static void +pmap_pvdump(pa) + vm_offset_t pa; +{ + pv_entry_t pv; + + printf("pa %x", pa); + m = PHYS_TO_VM_PAGE(pa); + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + printf(" -> pmap %x, va %x", + pv->pv_pmap, pv->pv_va); + pads(pv->pv_pmap); + } + printf(" "); +} +#endif +#endif diff --git a/sys/ia64/ia64/procfs_machdep.c b/sys/ia64/ia64/procfs_machdep.c new file mode 100644 index 0000000..000eb02 --- /dev/null +++ b/sys/ia64/ia64/procfs_machdep.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1993 Jan-Simon Pendry + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. + * + * @(#)procfs_machdep.c 8.3 (Berkeley) 1/27/94 + * + * From: + * $FreeBSD$ + */ + +/* + * Functions to be implemented here are: + * + * procfs_read_regs(proc, regs) + * Get the current user-visible register set from the process + * and copy it into the regs structure (<machine/reg.h>). + * The process is stopped at the time read_regs is called. + * + * procfs_write_regs(proc, regs) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * Depending on the architecture this may have fix-up work to do, + * especially if the IAR or PCW are modified. + * The process is stopped at the time write_regs is called. + * + * procfs_read_fpregs, procfs_write_fpregs + * deal with the floating point register set, otherwise as above. + * + * procfs_sstep(proc) + * Arrange for the process to trap after executing a single instruction. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/vnode.h> +#include <machine/reg.h> +#include <machine/md_var.h> +#include <miscfs/procfs/procfs.h> + +#include <vm/vm.h> +#include <sys/lock.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> + +#include <sys/user.h> + +int +procfs_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (fill_regs(p, regs)); +} + +int +procfs_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (set_regs(p, regs)); +} + +/* + * Ptrace doesn't support fpregs at all, and there are no security holes + * or translations for fpregs, so we can just copy them. + */ + +int +procfs_read_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (fill_fpregs(p, fpregs)); +} + +int +procfs_write_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + if ((p->p_flag & P_INMEM) == 0) + return (EIO); + return (set_fpregs(p, fpregs)); +} + +int +procfs_sstep(p) + struct proc *p; +{ + return (EINVAL); +} + +/* + * Placeholders + */ +int +procfs_read_dbregs(p, dbregs) + struct proc *p; + struct dbreg *dbregs; +{ + return (EIO); +} + +int +procfs_write_dbregs(p, dbregs) + struct proc *p; + struct dbreg *dbregs; +{ + return (EIO); +} diff --git a/sys/ia64/ia64/ssc.c b/sys/ia64/ia64/ssc.c new file mode 100644 index 0000000..ad6e4ed --- /dev/null +++ b/sys/ia64/ia64/ssc.c @@ -0,0 +1,263 @@ +/*- + * 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/kernel.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/ucred.h> +#include <sys/cons.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <sys/lock.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/vm_zone.h> + +#define SSC_GETCHAR 21 +#define SSC_PUTCHAR 31 + +#define SSC_POLL_HZ 50 + +static d_open_t sscopen; +static d_close_t sscclose; +static d_ioctl_t sscioctl; + +#define CDEV_MAJOR 97 +static struct cdevsw ssc_cdevsw = { + /* open */ sscopen, + /* close */ sscclose, + /* read */ ttyread, + /* write */ ttywrite, + /* ioctl */ sscioctl, + /* poll */ ttypoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "ssc", + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0, + /* bmaj */ -1 +}; + +static struct tty *ssc_tp = NULL; +static int polltime; +static struct callout_handle ssctimeouthandle + = CALLOUT_HANDLE_INITIALIZER(&ssctimeouthandle); + +static void sscstart(struct tty *); +static void ssctimeout(void *); +static int sscparam(struct tty *, struct termios *); +static void sscstop(struct tty *, int); + +static u_int64_t +ssc(u_int64_t in0, u_int64_t in1, u_int64_t in2, u_int64_t in3, int which) +{ + register u_int64_t ret0 __asm("r8"); + + __asm __volatile("mov r15=%1\n\t" + "break 0x80001" + : "=r"(ret0) + : "r"(which), "r"(in0), "r"(in1), "r"(in2), "r"(in3)); + return ret0; +} + +void +ssccnputc(dev_t dev, int c) +{ + ssc(c, 0, 0, 0, SSC_PUTCHAR); +} + +static int +ssccngetc(dev_t dev) +{ + return -1; +} + +static int +ssccncheckc(dev_t dev) +{ + return -1; +} + +static int +sscopen(dev_t dev, int flag, int mode, struct proc *p) +{ + struct tty *tp; + int s; + int error = 0, setuptimeout = 0; + + tp = ssc_tp = dev->si_tty = ttymalloc(ssc_tp); + + s = spltty(); + tp->t_oproc = sscstart; + tp->t_param = sscparam; + tp->t_stop = sscstop; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + tp->t_state |= TS_CARR_ON; + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG|CLOCAL; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; + ttsetwater(tp); + + setuptimeout = 1; + } else if ((tp->t_state & TS_XCLUDE) && suser(p)) { + splx(s); + return EBUSY; + } + + splx(s); + + error = (*linesw[tp->t_line].l_open)(dev, tp); + + if (error == 0 && setuptimeout) { + polltime = hz / SSC_POLL_HZ; + if (polltime < 1) + polltime = 1; + ssctimeouthandle = timeout(ssctimeout, tp, polltime); + } + return error; +} + +static int +sscclose(dev_t dev, int flag, int mode, struct proc *p) +{ + int unit = minor(dev); + struct tty *tp = ssc_tp; + + if (unit != 0) + return ENXIO; + + untimeout(ssctimeout, tp, ssctimeouthandle); + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return 0; +} + +static int +sscioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + int unit = minor(dev); + struct tty *tp = ssc_tp; + int error; + + if (unit != 0) + return ENXIO; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error != ENOIOCTL) + return error; + error = ttioctl(tp, cmd, data, flag); + if (error != ENOIOCTL) + return error; + + return ENOTTY; +} + +static int +sscparam(struct tty *tp, struct termios *t) +{ + + return 0; +} + +static void +sscstart(struct tty *tp) +{ + int s; + + s = spltty(); + + if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { + ttwwakeup(tp); + splx(s); + return; + } + + tp->t_state |= TS_BUSY; + while (tp->t_outq.c_cc != 0) + ssccnputc(tp->t_dev, getc(&tp->t_outq)); + tp->t_state &= ~TS_BUSY; + + ttwwakeup(tp); + splx(s); +} + +/* + * Stop output on a line. + */ +static void +sscstop(struct tty *tp, int flag) +{ + int s; + + s = spltty(); + if (tp->t_state & TS_BUSY) + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + splx(s); +} + +static void +ssctimeout(void *v) +{ + struct tty *tp = v; + int c; + + while ((c = ssccncheckc(tp->t_dev)) != -1) { + if (tp->t_state & TS_ISOPEN) + (*linesw[tp->t_line].l_rint)(c, tp); + } + ssctimeouthandle = timeout(ssctimeout, tp, polltime); +} + +CONS_DRIVER(ssc, NULL, NULL, NULL, ssccngetc, ssccncheckc, ssccnputc, NULL); + +void +ssccnattach(void) +{ + cn_tab = &ssc_consdev; + ssc_consdev.cn_pri = CN_NORMAL; + ssc_consdev.cn_dev = makedev(CDEV_MAJOR, 0); + make_dev(&ssc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "ssccons"); +} + diff --git a/sys/ia64/ia64/support.S b/sys/ia64/ia64/support.S new file mode 100644 index 0000000..91e3856 --- /dev/null +++ b/sys/ia64/ia64/support.S @@ -0,0 +1,662 @@ +/*- + * 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$ + */ +/* + * 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 <machine/asm.h> +#include <assym.s> + + .text + +/**************************************************************************/ + +/* + * fu{byte,word} : fetch a byte (word) from user memory + */ + + LEAF(suword, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + stq a1, 0(a0) /* try the store */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET +#endif + END(suword) + + LEAF(subyte, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + zap a1, 0xfe, a1 /* mask off the byte to store */ + insbl a1, a0, a1 /* shift it to the right place */ + ldq_u t0, 0(a0) /* read the qword to store it in */ + mskbl t0, a0, t0 /* make a place for our byte */ + or a1, t0, a1 /* move it in */ + stq_u a1, 0(a0) /* and put the byte back */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET +#endif + END(subyte) + + LEAF(fuword, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + ldq v0, 0(a0) /* try the fetch */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + RET +#endif + END(fuword) + + LEAF(fubyte, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + ldq_u v0, 0(a0) /* get the word containing our byte */ + extbl v0, a0, v0 /* extract the byte */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + RET +#endif + END(fubyte) + + LEAF(suibyte, 2) +#if 0 + ldiq v0, -1 + RET +#endif + END(suibyte) + + LEAF(fusufault, 0) +#if 0 + ldq t0, curproc + ldq t0, P_ADDR(t0) + stq zero, U_PCB_ONFAULT(t0) + ldiq v0, -1 + RET +#endif + END(fusufault) + +LEAF(fswintrberr, 0) +XLEAF(fuswintr) /* XXX what is a 'word'? */ +XLEAF(suswintr) /* XXX what is a 'word'? */ +#if 0 + LDGP(pv) + ldiq v0, -1 + RET +#endif + END(fswintrberr) + +/**************************************************************************/ + +/* + * Copy a null-terminated string within the kernel's address space. + * If lenp is not NULL, store the number of chars copied in *lenp + * + * int copystr(char *from, char *to, size_t len, size_t *lenp); + */ +LEAF(copystr, 4) +#if 0 + LDGP(pv) + + mov a2, t0 /* t0 = i = len */ + beq a2, Lcopystr2 /* if (len == 0), bail out */ + +Lcopystr1: + ldq_u t1, 0(a0) /* t1 = *from */ + extbl t1, a0, t1 + ldq_u t3, 0(a1) /* set up t2 with quad around *to */ + insbl t1, a1, t2 + mskbl t3, a1, t3 + or t3, t2, t3 /* add *from to quad around *to */ + stq_u t3, 0(a1) /* write out that quad */ + + subl a2, 1, a2 /* len-- */ + beq t1, Lcopystr2 /* if (*from == 0), bail out */ + addq a1, 1, a1 /* to++ */ + addq a0, 1, a0 /* from++ */ + bne a2, Lcopystr1 /* if (len != 0) copy more */ + +Lcopystr2: + beq a3, Lcopystr3 /* if (lenp != NULL) */ + subl t0, a2, t0 /* *lenp = (i - len) */ + stq t0, 0(a3) +Lcopystr3: + beq t1, Lcopystr4 /* *from == '\0'; leave quietly */ + + ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */ + RET + +Lcopystr4: + mov zero, v0 /* return 0. */ + RET +#endif + END(copystr) + +LEAF(copyinstr, 4) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ + cmpult a0, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(copystr) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + RET /* v0 left over from copystr */ +#endif + END(copyinstr) + +LEAF(copyoutstr, 4) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ + cmpult a1, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(copystr) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + RET /* v0 left over from copystr */ +#endif + END(copyoutstr) + +/* + * Alternative memory mover + */ + LEAF(memcpy,3) +#if 0 + mov a0,t0 + mov a1,a0 + mov t0,a1 + br bcopy +#endif + END(memcpy) + +/* + * Copy a bytes within the kernel's address space. + * + * In the kernel, bcopy() doesn't have to handle the overlapping + * case; that's that ovbcopy() is for. However, it doesn't hurt + * to do both in bcopy, and it does provide a measure of safety. + * + * void bcopy(char *from, char *to, size_t len); + * void ovbcopy(char *from, char *to, size_t len); + */ +LEAF(bcopy,3) +XLEAF(ovbcopy) +#if 0 + /* Check for negative length */ + ble a2,bcopy_done + + /* Check for overlap */ + subq a1,a0,t5 + cmpult t5,a2,t5 + bne t5,bcopy_overlap + + /* a3 = end address */ + addq a0,a2,a3 + + /* Get the first word */ + ldq_u t2,0(a0) + + /* Do they have the same alignment? */ + xor a0,a1,t0 + and t0,7,t0 + and a1,7,t1 + bne t0,bcopy_different_alignment + + /* src & dst have same alignment */ + beq t1,bcopy_all_aligned + + ldq_u t3,0(a1) + addq a2,t1,a2 + mskqh t2,a0,t2 + mskql t3,a0,t3 + or t2,t3,t2 + + /* Dst is 8-byte aligned */ + +bcopy_all_aligned: + /* If less than 8 bytes,skip loop */ + subq a2,1,t0 + and a2,7,a2 + bic t0,7,t0 + beq t0,bcopy_samealign_lp_end + +bcopy_samealign_lp: + stq_u t2,0(a1) + addq a1,8,a1 + ldq_u t2,8(a0) + subq t0,8,t0 + addq a0,8,a0 + bne t0,bcopy_samealign_lp + +bcopy_samealign_lp_end: + /* If we're done, exit */ + bne a2,bcopy_small_left + stq_u t2,0(a1) + RET + +bcopy_small_left: + mskql t2,a2,t4 + ldq_u t3,0(a1) + mskqh t3,a2,t3 + or t4,t3,t4 + stq_u t4,0(a1) + RET + +bcopy_different_alignment: + /* + * this is the fun part + */ + addq a0,a2,a3 + cmpule a2,8,t0 + bne t0,bcopy_da_finish + + beq t1,bcopy_da_noentry + + /* Do the initial partial word */ + subq zero,a1,t0 + and t0,7,t0 + ldq_u t3,7(a0) + extql t2,a0,t2 + extqh t3,a0,t3 + or t2,t3,t5 + insql t5,a1,t5 + ldq_u t6,0(a1) + mskql t6,a1,t6 + or t5,t6,t5 + stq_u t5,0(a1) + addq a0,t0,a0 + addq a1,t0,a1 + subq a2,t0,a2 + ldq_u t2,0(a0) + +bcopy_da_noentry: + subq a2,1,t0 + bic t0,7,t0 + and a2,7,a2 + beq t0,bcopy_da_finish2 + +bcopy_da_lp: + ldq_u t3,7(a0) + addq a0,8,a0 + extql t2,a0,t4 + extqh t3,a0,t5 + subq t0,8,t0 + or t4,t5,t5 + stq t5,0(a1) + addq a1,8,a1 + beq t0,bcopy_da_finish1 + ldq_u t2,7(a0) + addq a0,8,a0 + extql t3,a0,t4 + extqh t2,a0,t5 + subq t0,8,t0 + or t4,t5,t5 + stq t5,0(a1) + addq a1,8,a1 + bne t0,bcopy_da_lp + +bcopy_da_finish2: + /* Do the last new word */ + mov t2,t3 + +bcopy_da_finish1: + /* Do the last partial word */ + ldq_u t2,-1(a3) + extql t3,a0,t3 + extqh t2,a0,t2 + or t2,t3,t2 + br zero,bcopy_samealign_lp_end + +bcopy_da_finish: + /* Do the last word in the next source word */ + ldq_u t3,-1(a3) + extql t2,a0,t2 + extqh t3,a0,t3 + or t2,t3,t2 + insqh t2,a1,t3 + insql t2,a1,t2 + lda t4,-1(zero) + mskql t4,a2,t5 + cmovne t5,t5,t4 + insqh t4,a1,t5 + insql t4,a1,t4 + addq a1,a2,a4 + ldq_u t6,0(a1) + ldq_u t7,-1(a4) + bic t6,t4,t6 + bic t7,t5,t7 + and t2,t4,t2 + and t3,t5,t3 + or t2,t6,t2 + or t3,t7,t3 + stq_u t3,-1(a4) + stq_u t2,0(a1) + RET + +bcopy_overlap: + /* + * Basically equivalent to previous case, only backwards. + * Not quite as highly optimized + */ + addq a0,a2,a3 + addq a1,a2,a4 + + /* less than 8 bytes - don't worry about overlap */ + cmpule a2,8,t0 + bne t0,bcopy_ov_short + + /* Possibly do a partial first word */ + and a4,7,t4 + beq t4,bcopy_ov_nostart2 + subq a3,t4,a3 + subq a4,t4,a4 + ldq_u t1,0(a3) + subq a2,t4,a2 + ldq_u t2,7(a3) + ldq t3,0(a4) + extql t1,a3,t1 + extqh t2,a3,t2 + or t1,t2,t1 + mskqh t3,t4,t3 + mskql t1,t4,t1 + or t1,t3,t1 + stq t1,0(a4) + +bcopy_ov_nostart2: + bic a2,7,t4 + and a2,7,a2 + beq t4,bcopy_ov_lp_end + +bcopy_ov_lp: + /* This could be more pipelined, but it doesn't seem worth it */ + ldq_u t0,-8(a3) + subq a4,8,a4 + ldq_u t1,-1(a3) + subq a3,8,a3 + extql t0,a3,t0 + extqh t1,a3,t1 + subq t4,8,t4 + or t0,t1,t0 + stq t0,0(a4) + bne t4,bcopy_ov_lp + +bcopy_ov_lp_end: + beq a2,bcopy_done + + ldq_u t0,0(a0) + ldq_u t1,7(a0) + ldq_u t2,0(a1) + extql t0,a0,t0 + extqh t1,a0,t1 + or t0,t1,t0 + insql t0,a1,t0 + mskql t2,a1,t2 + or t2,t0,t2 + stq_u t2,0(a1) + +bcopy_done: + RET + +bcopy_ov_short: + ldq_u t2,0(a0) + br zero,bcopy_da_finish +#endif + END(bcopy) + +LEAF(copyin, 3) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ + cmpult a0, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(bcopy) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + mov zero, v0 /* return 0. */ + RET +#endif + END(copyin) + +LEAF(copyout, 3) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ + cmpult a1, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(bcopy) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + mov zero, v0 /* return 0. */ + RET +#endif + END(copyout) + +LEAF(copyerr, 0) +#if 0 + ldq t0, curproc + ldq t0, P_ADDR(t0) + stq zero, U_PCB_ONFAULT(t0) /* reset fault handler. */ + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + ldiq v0, EFAULT /* return EFAULT. */ + RET +#endif + END(copyerr) + +/**************************************************************************/ + +/* + * Kernel setjmp and longjmp. Rather minimalist. + * + * longjmp(label_t *a) + * will generate a "return (1)" from the last call to + * setjmp(label_t *a) + * by restoring registers from the stack, + */ + + +LEAF(setjmp, 1) +#if 0 + LDGP(pv) + + stq ra, (0 * 8)(a0) /* return address */ + stq s0, (1 * 8)(a0) /* callee-saved registers */ + stq s1, (2 * 8)(a0) + stq s2, (3 * 8)(a0) + stq s3, (4 * 8)(a0) + stq s4, (5 * 8)(a0) + stq s5, (6 * 8)(a0) + stq s6, (7 * 8)(a0) + stq sp, (8 * 8)(a0) + + ldiq t0, 0xbeeffedadeadbabe /* set magic number */ + stq t0, (9 * 8)(a0) + + mov zero, v0 /* return zero */ + RET +#endif +END(setjmp) + +LEAF(longjmp, 1) +#if 0 + LDGP(pv) + + ldiq t0, 0xbeeffedadeadbabe /* check magic number */ + ldq t1, (9 * 8)(a0) + cmpeq t0, t1, t0 + beq t0, longjmp_botch /* if bad, punt */ + + ldq ra, (0 * 8)(a0) /* return address */ + ldq s0, (1 * 8)(a0) /* callee-saved registers */ + ldq s1, (2 * 8)(a0) + ldq s2, (3 * 8)(a0) + ldq s3, (4 * 8)(a0) + ldq s4, (5 * 8)(a0) + ldq s5, (6 * 8)(a0) + ldq s6, (7 * 8)(a0) + ldq sp, (8 * 8)(a0) + + ldiq v0, 1 + RET + +longjmp_botch: + lda a0, longjmp_botchmsg + mov ra, a1 + CALL(panic) + call_pal PAL_bugchk + + .data +longjmp_botchmsg: + .asciz "longjmp botch from %p" + .text +#endif +END(longjmp) diff --git a/sys/ia64/ia64/support.s b/sys/ia64/ia64/support.s new file mode 100644 index 0000000..91e3856 --- /dev/null +++ b/sys/ia64/ia64/support.s @@ -0,0 +1,662 @@ +/*- + * 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$ + */ +/* + * 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 <machine/asm.h> +#include <assym.s> + + .text + +/**************************************************************************/ + +/* + * fu{byte,word} : fetch a byte (word) from user memory + */ + + LEAF(suword, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + stq a1, 0(a0) /* try the store */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET +#endif + END(suword) + + LEAF(subyte, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + zap a1, 0xfe, a1 /* mask off the byte to store */ + insbl a1, a0, a1 /* shift it to the right place */ + ldq_u t0, 0(a0) /* read the qword to store it in */ + mskbl t0, a0, t0 /* make a place for our byte */ + or a1, t0, a1 /* move it in */ + stq_u a1, 0(a0) /* and put the byte back */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + mov zero, v0 + RET +#endif + END(subyte) + + LEAF(fuword, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + ldq v0, 0(a0) /* try the fetch */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + RET +#endif + END(fuword) + + LEAF(fubyte, 1) +#if 0 + LDGP(pv) + + ldiq t0, VM_MAXUSER_ADDRESS /* verify address validity */ + cmpult a0, t0, t1 + beq t1, fusufault + + lda t0, fusufault /* trap faults */ + ldq t2, curproc + ldq t2, P_ADDR(t2) + stq t0, U_PCB_ONFAULT(t2) + + ldq_u v0, 0(a0) /* get the word containing our byte */ + extbl v0, a0, v0 /* extract the byte */ + + stq zero, U_PCB_ONFAULT(t2) /* clean up */ + + RET +#endif + END(fubyte) + + LEAF(suibyte, 2) +#if 0 + ldiq v0, -1 + RET +#endif + END(suibyte) + + LEAF(fusufault, 0) +#if 0 + ldq t0, curproc + ldq t0, P_ADDR(t0) + stq zero, U_PCB_ONFAULT(t0) + ldiq v0, -1 + RET +#endif + END(fusufault) + +LEAF(fswintrberr, 0) +XLEAF(fuswintr) /* XXX what is a 'word'? */ +XLEAF(suswintr) /* XXX what is a 'word'? */ +#if 0 + LDGP(pv) + ldiq v0, -1 + RET +#endif + END(fswintrberr) + +/**************************************************************************/ + +/* + * Copy a null-terminated string within the kernel's address space. + * If lenp is not NULL, store the number of chars copied in *lenp + * + * int copystr(char *from, char *to, size_t len, size_t *lenp); + */ +LEAF(copystr, 4) +#if 0 + LDGP(pv) + + mov a2, t0 /* t0 = i = len */ + beq a2, Lcopystr2 /* if (len == 0), bail out */ + +Lcopystr1: + ldq_u t1, 0(a0) /* t1 = *from */ + extbl t1, a0, t1 + ldq_u t3, 0(a1) /* set up t2 with quad around *to */ + insbl t1, a1, t2 + mskbl t3, a1, t3 + or t3, t2, t3 /* add *from to quad around *to */ + stq_u t3, 0(a1) /* write out that quad */ + + subl a2, 1, a2 /* len-- */ + beq t1, Lcopystr2 /* if (*from == 0), bail out */ + addq a1, 1, a1 /* to++ */ + addq a0, 1, a0 /* from++ */ + bne a2, Lcopystr1 /* if (len != 0) copy more */ + +Lcopystr2: + beq a3, Lcopystr3 /* if (lenp != NULL) */ + subl t0, a2, t0 /* *lenp = (i - len) */ + stq t0, 0(a3) +Lcopystr3: + beq t1, Lcopystr4 /* *from == '\0'; leave quietly */ + + ldiq v0, ENAMETOOLONG /* *from != '\0'; error. */ + RET + +Lcopystr4: + mov zero, v0 /* return 0. */ + RET +#endif + END(copystr) + +LEAF(copyinstr, 4) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ + cmpult a0, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(copystr) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + RET /* v0 left over from copystr */ +#endif + END(copyinstr) + +LEAF(copyoutstr, 4) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ + cmpult a1, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(copystr) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + RET /* v0 left over from copystr */ +#endif + END(copyoutstr) + +/* + * Alternative memory mover + */ + LEAF(memcpy,3) +#if 0 + mov a0,t0 + mov a1,a0 + mov t0,a1 + br bcopy +#endif + END(memcpy) + +/* + * Copy a bytes within the kernel's address space. + * + * In the kernel, bcopy() doesn't have to handle the overlapping + * case; that's that ovbcopy() is for. However, it doesn't hurt + * to do both in bcopy, and it does provide a measure of safety. + * + * void bcopy(char *from, char *to, size_t len); + * void ovbcopy(char *from, char *to, size_t len); + */ +LEAF(bcopy,3) +XLEAF(ovbcopy) +#if 0 + /* Check for negative length */ + ble a2,bcopy_done + + /* Check for overlap */ + subq a1,a0,t5 + cmpult t5,a2,t5 + bne t5,bcopy_overlap + + /* a3 = end address */ + addq a0,a2,a3 + + /* Get the first word */ + ldq_u t2,0(a0) + + /* Do they have the same alignment? */ + xor a0,a1,t0 + and t0,7,t0 + and a1,7,t1 + bne t0,bcopy_different_alignment + + /* src & dst have same alignment */ + beq t1,bcopy_all_aligned + + ldq_u t3,0(a1) + addq a2,t1,a2 + mskqh t2,a0,t2 + mskql t3,a0,t3 + or t2,t3,t2 + + /* Dst is 8-byte aligned */ + +bcopy_all_aligned: + /* If less than 8 bytes,skip loop */ + subq a2,1,t0 + and a2,7,a2 + bic t0,7,t0 + beq t0,bcopy_samealign_lp_end + +bcopy_samealign_lp: + stq_u t2,0(a1) + addq a1,8,a1 + ldq_u t2,8(a0) + subq t0,8,t0 + addq a0,8,a0 + bne t0,bcopy_samealign_lp + +bcopy_samealign_lp_end: + /* If we're done, exit */ + bne a2,bcopy_small_left + stq_u t2,0(a1) + RET + +bcopy_small_left: + mskql t2,a2,t4 + ldq_u t3,0(a1) + mskqh t3,a2,t3 + or t4,t3,t4 + stq_u t4,0(a1) + RET + +bcopy_different_alignment: + /* + * this is the fun part + */ + addq a0,a2,a3 + cmpule a2,8,t0 + bne t0,bcopy_da_finish + + beq t1,bcopy_da_noentry + + /* Do the initial partial word */ + subq zero,a1,t0 + and t0,7,t0 + ldq_u t3,7(a0) + extql t2,a0,t2 + extqh t3,a0,t3 + or t2,t3,t5 + insql t5,a1,t5 + ldq_u t6,0(a1) + mskql t6,a1,t6 + or t5,t6,t5 + stq_u t5,0(a1) + addq a0,t0,a0 + addq a1,t0,a1 + subq a2,t0,a2 + ldq_u t2,0(a0) + +bcopy_da_noentry: + subq a2,1,t0 + bic t0,7,t0 + and a2,7,a2 + beq t0,bcopy_da_finish2 + +bcopy_da_lp: + ldq_u t3,7(a0) + addq a0,8,a0 + extql t2,a0,t4 + extqh t3,a0,t5 + subq t0,8,t0 + or t4,t5,t5 + stq t5,0(a1) + addq a1,8,a1 + beq t0,bcopy_da_finish1 + ldq_u t2,7(a0) + addq a0,8,a0 + extql t3,a0,t4 + extqh t2,a0,t5 + subq t0,8,t0 + or t4,t5,t5 + stq t5,0(a1) + addq a1,8,a1 + bne t0,bcopy_da_lp + +bcopy_da_finish2: + /* Do the last new word */ + mov t2,t3 + +bcopy_da_finish1: + /* Do the last partial word */ + ldq_u t2,-1(a3) + extql t3,a0,t3 + extqh t2,a0,t2 + or t2,t3,t2 + br zero,bcopy_samealign_lp_end + +bcopy_da_finish: + /* Do the last word in the next source word */ + ldq_u t3,-1(a3) + extql t2,a0,t2 + extqh t3,a0,t3 + or t2,t3,t2 + insqh t2,a1,t3 + insql t2,a1,t2 + lda t4,-1(zero) + mskql t4,a2,t5 + cmovne t5,t5,t4 + insqh t4,a1,t5 + insql t4,a1,t4 + addq a1,a2,a4 + ldq_u t6,0(a1) + ldq_u t7,-1(a4) + bic t6,t4,t6 + bic t7,t5,t7 + and t2,t4,t2 + and t3,t5,t3 + or t2,t6,t2 + or t3,t7,t3 + stq_u t3,-1(a4) + stq_u t2,0(a1) + RET + +bcopy_overlap: + /* + * Basically equivalent to previous case, only backwards. + * Not quite as highly optimized + */ + addq a0,a2,a3 + addq a1,a2,a4 + + /* less than 8 bytes - don't worry about overlap */ + cmpule a2,8,t0 + bne t0,bcopy_ov_short + + /* Possibly do a partial first word */ + and a4,7,t4 + beq t4,bcopy_ov_nostart2 + subq a3,t4,a3 + subq a4,t4,a4 + ldq_u t1,0(a3) + subq a2,t4,a2 + ldq_u t2,7(a3) + ldq t3,0(a4) + extql t1,a3,t1 + extqh t2,a3,t2 + or t1,t2,t1 + mskqh t3,t4,t3 + mskql t1,t4,t1 + or t1,t3,t1 + stq t1,0(a4) + +bcopy_ov_nostart2: + bic a2,7,t4 + and a2,7,a2 + beq t4,bcopy_ov_lp_end + +bcopy_ov_lp: + /* This could be more pipelined, but it doesn't seem worth it */ + ldq_u t0,-8(a3) + subq a4,8,a4 + ldq_u t1,-1(a3) + subq a3,8,a3 + extql t0,a3,t0 + extqh t1,a3,t1 + subq t4,8,t4 + or t0,t1,t0 + stq t0,0(a4) + bne t4,bcopy_ov_lp + +bcopy_ov_lp_end: + beq a2,bcopy_done + + ldq_u t0,0(a0) + ldq_u t1,7(a0) + ldq_u t2,0(a1) + extql t0,a0,t0 + extqh t1,a0,t1 + or t0,t1,t0 + insql t0,a1,t0 + mskql t2,a1,t2 + or t2,t0,t2 + stq_u t2,0(a1) + +bcopy_done: + RET + +bcopy_ov_short: + ldq_u t2,0(a0) + br zero,bcopy_da_finish +#endif + END(bcopy) + +LEAF(copyin, 3) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that src addr */ + cmpult a0, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(bcopy) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + mov zero, v0 /* return 0. */ + RET +#endif + END(copyin) + +LEAF(copyout, 3) +#if 0 + LDGP(pv) + lda sp, -16(sp) /* set up stack frame */ + stq ra, (16-8)(sp) /* save ra */ + ldiq t0, VM_MAXUSER_ADDRESS /* make sure that dest addr */ + cmpult a1, t0, t1 /* is in user space. */ + beq t1, copyerr /* if it's not, error out. */ + lda v0, copyerr /* set up fault handler. */ + .set noat + ldq at_reg, curproc + ldq at_reg, P_ADDR(at_reg) + stq v0, U_PCB_ONFAULT(at_reg) + .set at + CALL(bcopy) /* do the copy. */ + .set noat + ldq at_reg, curproc /* kill the fault handler. */ + ldq at_reg, P_ADDR(at_reg) + stq zero, U_PCB_ONFAULT(at_reg) + .set at + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + mov zero, v0 /* return 0. */ + RET +#endif + END(copyout) + +LEAF(copyerr, 0) +#if 0 + ldq t0, curproc + ldq t0, P_ADDR(t0) + stq zero, U_PCB_ONFAULT(t0) /* reset fault handler. */ + ldq ra, (16-8)(sp) /* restore ra. */ + lda sp, 16(sp) /* kill stack frame. */ + ldiq v0, EFAULT /* return EFAULT. */ + RET +#endif + END(copyerr) + +/**************************************************************************/ + +/* + * Kernel setjmp and longjmp. Rather minimalist. + * + * longjmp(label_t *a) + * will generate a "return (1)" from the last call to + * setjmp(label_t *a) + * by restoring registers from the stack, + */ + + +LEAF(setjmp, 1) +#if 0 + LDGP(pv) + + stq ra, (0 * 8)(a0) /* return address */ + stq s0, (1 * 8)(a0) /* callee-saved registers */ + stq s1, (2 * 8)(a0) + stq s2, (3 * 8)(a0) + stq s3, (4 * 8)(a0) + stq s4, (5 * 8)(a0) + stq s5, (6 * 8)(a0) + stq s6, (7 * 8)(a0) + stq sp, (8 * 8)(a0) + + ldiq t0, 0xbeeffedadeadbabe /* set magic number */ + stq t0, (9 * 8)(a0) + + mov zero, v0 /* return zero */ + RET +#endif +END(setjmp) + +LEAF(longjmp, 1) +#if 0 + LDGP(pv) + + ldiq t0, 0xbeeffedadeadbabe /* check magic number */ + ldq t1, (9 * 8)(a0) + cmpeq t0, t1, t0 + beq t0, longjmp_botch /* if bad, punt */ + + ldq ra, (0 * 8)(a0) /* return address */ + ldq s0, (1 * 8)(a0) /* callee-saved registers */ + ldq s1, (2 * 8)(a0) + ldq s2, (3 * 8)(a0) + ldq s3, (4 * 8)(a0) + ldq s4, (5 * 8)(a0) + ldq s5, (6 * 8)(a0) + ldq s6, (7 * 8)(a0) + ldq sp, (8 * 8)(a0) + + ldiq v0, 1 + RET + +longjmp_botch: + lda a0, longjmp_botchmsg + mov ra, a1 + CALL(panic) + call_pal PAL_bugchk + + .data +longjmp_botchmsg: + .asciz "longjmp botch from %p" + .text +#endif +END(longjmp) diff --git a/sys/ia64/ia64/swtch.s b/sys/ia64/ia64/swtch.s new file mode 100644 index 0000000..b7f4de1 --- /dev/null +++ b/sys/ia64/ia64/swtch.s @@ -0,0 +1,155 @@ +/*- + * 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 <machine/asm.h> +#include <machine/mutex.h> +#include "assym.s" + +/**************************************************************************/ + +/* + * savectx: save process context, i.e. callee-saved registers + * + * Arguments: + * in0 'struct pcb *' of the process that needs its context saved + * + * Return: + * ret0 0. (note that for child processes, it seems + * like savectx() returns 1, because the return address + * in the PCB is set to the return address from savectx().) + */ + +LEAF(savectx, 1) + alloc r2=ar.pfs,1,0,0,0 + ;; + flushrs // push out caller's dirty regs + mov r3=ar.unat // caller's value for ar.unat + ;; + mov ar.rsc=r0 // stop the RSE after the flush + ;; + mov r16=ar.rnat // read RSE's NaT collection + mov r17=in0 + mov r18=ar.bspstore + ;; + st8.spill [r17]=r4,8 ;; // save r4..r6 + st8.spill [r17]=r5,8 ;; // and accumulate NaT bits + st8.spill [r17]=r6,8 ;; + st8.spill [r17]=r7,8 ;; + + stf.spill [r17]=f2,16 ;; // save f2..f5 with NaTVals + stf.spill [r17]=f3,16 ;; + stf.spill [r17]=f4,16 ;; + stf.spill [r17]=f5,16 ;; + + mov r19=ar.unat // NaT bits for r4..r6 + mov r20=pr + mov r21=rp + mov ret0=r0 // return zero + + st8 [r17]=r3,8 ;; // save caller's ar.unat + st8 [r17]=sp,8 ;; // stack pointer + st8 [r17]=r2,8 ;; // ar.pfs + st8 [r17]=r18,8 ;; // ar.bspstore + st8 [r17]=r19,8 ;; // our NaT bits + st8 [r17]=r16,8 ;; // ar.rnat + st8 [r17]=r20,8 ;; // pr + st8 [r17]=r21,8 ;; // return address + + mov ar.rsc=3 // turn RSE back on + + br.ret.sptk.few rp + END(savectx) + +/* + * restorectx: restore process context, i.e. callee-saved registers + * + * Arguments: + * in0 'struct pcb *' of the process being restored + * + * Return: + * Does not return. We arrange things so that savectx appears to + * return a second time with a non-zero return value. + */ + +LEAF(restorectx, 1) + alloc r2=ar.pfs,1,0,0,0 + + add r3=U_PCB_UNAT,in0 // point at NaT for r4..r7 + mov ar.rsc=r0 ;; // switch off the RSE + ld8 r16=[r3] // load NaT for r4..r7 + ;; + ld8.fill r4=[in0],8 ;; // restore r4 + ld8.fill r5=[in0],8 ;; // restore r5 + ld8.fill r6=[in0],8 ;; // restore r6 + ld8.fill r7=[in0],8 ;; // restore r7 + + ldf.fill f2=[in0],8 ;; // restore f2 + ldf.fill f3=[in0],8 ;; // restore f3 + ldf.fill f4=[in0],8 ;; // restore f4 + ldf.fill f5=[in0],8 ;; // restore f5 + + ld8 r16=[in0],8 ;; // caller's ar.unat + ld8 sp=[in0],8 ;; // stack pointer + ld8 r17=[in0],8 ;; // ar.pfs + ld8 r18=[in0],16 ;; // ar.bspstore, skip ar.unat + ld8 r19=[in0],8 ;; // ar.rnat + ld8 r20=[in0],8 ;; // pr + ld8 r21=[in0],8 ;; // iip + + mov ar.unat=r16 + mov ar.pfs=r17 + mov ar.bspstore=r18 ;; + mov ar.rnat=r19 + mov pr=r20,0x1ffff + mov rp=r21 + mov ret0=r21 // non-zero return + ;; + loadrs + mov ar.rsc=3 // restart RSE + ;; + br.ret.sptk.few rp + END(restorectx) + +/**************************************************************************/ + +IMPORT(want_resched, 4) + +/* + * switch_trampoline() + * + * Arrange for a function to be invoked neatly, after a cpu_switch(). + * + * Invokes the function specified by the s0 register with the return + * address specified by the s1 register and with one argument, a + * pointer to the executing process's proc structure. + */ +LEAF(switch_trampoline, 0) + MTX_EXIT(sched_lock#, r14, r15) + /* XXX write this */ + END(switch_trampoline) + diff --git a/sys/ia64/ia64/synch_machdep.c b/sys/ia64/ia64/synch_machdep.c new file mode 100644 index 0000000..ebcd7a4 --- /dev/null +++ b/sys/ia64/ia64/synch_machdep.c @@ -0,0 +1,562 @@ +/*- + * Copyright (c) 1997, 1998 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: synch_machdep.c,v 2.3.2.39 2000/04/27 03:10:25 cp Exp $ + * $FreeBSD$ + */ + +#define MTX_STRS /* define common strings */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> +#include <vm/vm_map.h> +#include <sys/user.h> +#include <ddb/ddb.h> +#include <machine/atomic.h> +#include <machine/clock.h> +#include <machine/cpu.h> +#include <machine/mutex.h> + +/* All mutexes in system (used for debug/panic) */ +struct mtx all_mtx = { MTX_UNOWNED, 0, 0, "All mutexes queue head", + TAILQ_HEAD_INITIALIZER(all_mtx.mtx_blocked), + { NULL, NULL }, &all_mtx, &all_mtx +#ifdef SMP_DEBUG + , NULL, { NULL, NULL }, NULL, 0 +#endif +}; + +int mtx_cur_cnt; +int mtx_max_cnt; + +extern void _mtx_enter_giant_def(void); +extern void _mtx_exit_giant_def(void); + +static void propagate_priority(struct proc *) __unused; + +#define mtx_unowned(m) ((m)->mtx_lock == MTX_UNOWNED) +#define mtx_owner(m) (mtx_unowned(m) ? NULL \ + : (struct proc *)((m)->mtx_lock & MTX_FLAGMASK)) + +#define RETIP(x) *(((u_int64_t *)(&x)) - 1) +#define SET_PRIO(p, pri) (p)->p_priority = (pri) + +/* + * XXX Temporary, for use from assembly language + */ + +void +_mtx_enter_giant_def(void) +{ + + mtx_enter(&Giant, MTX_DEF); +} + +void +_mtx_exit_giant_def(void) +{ + + mtx_exit(&Giant, MTX_DEF); +} + +static void +propagate_priority(struct proc *p) +{ + int pri = p->p_priority; + struct mtx *m = p->p_blocked; + + for (;;) { + struct proc *p1; + + p = mtx_owner(m); + + if (p == NULL) { + /* + * This really isn't quite right. Really + * ought to bump priority of process that + * next acquires the mutex. + */ + MPASS(m->mtx_lock == MTX_CONTESTED); + return; + } + MPASS(p->p_magic == P_MAGIC); + if (p->p_priority <= pri) + return; + /* + * If lock holder is actually running, just bump priority. + */ + if (TAILQ_NEXT(p, p_procq) == NULL) { + MPASS(p->p_stat == SRUN || p->p_stat == SZOMB); + SET_PRIO(p, pri); + return; + } + /* + * If on run queue move to new run queue, and + * quit. + */ + if (p->p_stat == SRUN) { + MPASS(p->p_blocked == NULL); + remrunqueue(p); + SET_PRIO(p, pri); + setrunqueue(p); + return; + } + + /* + * If we aren't blocked on a mutex, give up and quit. + */ + if (p->p_stat != SMTX) { + return; + } + + /* + * Pick up the mutex that p is blocked on. + */ + m = p->p_blocked; + MPASS(m != NULL); + + /* + * Check if the proc needs to be moved up on + * the blocked chain + */ + if ((p1 = TAILQ_PREV(p, rq, p_procq)) == NULL || + p1->p_priority <= pri) + continue; + + /* + * Remove proc from blocked chain + */ + TAILQ_REMOVE(&m->mtx_blocked, p, p_procq); + TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) { + MPASS(p1->p_magic == P_MAGIC); + if (p1->p_priority > pri) + break; + } + if (p1) + TAILQ_INSERT_BEFORE(p1, p, p_procq); + else + TAILQ_INSERT_TAIL(&m->mtx_blocked, p, p_procq); + CTR4(KTR_LOCK, + "propagate priority: p 0x%p moved before 0x%p on [0x%p] %s", + p, p1, m, m->mtx_description); + } +} + +void +mtx_enter_hard(struct mtx *m, int type, int psr) +{ + struct proc *p = CURPROC; + + KASSERT(p != NULL, ("curproc is NULL in mutex")); + + switch (type) { + case MTX_DEF: + if ((m->mtx_lock & MTX_FLAGMASK) == (u_int64_t)p) { + m->mtx_recurse++; + atomic_set_64(&m->mtx_lock, MTX_RECURSE); + CTR1(KTR_LOCK, "mtx_enter: 0x%p recurse", m); + return; + } + CTR3(KTR_LOCK, "mtx_enter: 0x%p contested (lock=%lx) [0x%lx]", + m, m->mtx_lock, RETIP(m)); + while (!atomic_cmpset_64(&m->mtx_lock, MTX_UNOWNED, + (u_int64_t)p)) { + int v; + struct proc *p1; + + mtx_enter(&sched_lock, MTX_SPIN | MTX_RLIKELY); + /* + * check if the lock has been released while + * waiting for the schedlock. + */ + if ((v = m->mtx_lock) == MTX_UNOWNED) { + mtx_exit(&sched_lock, MTX_SPIN); + continue; + } + /* + * The mutex was marked contested on release. This + * means that there are processes blocked on it. + */ + if (v == MTX_CONTESTED) { + p1 = TAILQ_FIRST(&m->mtx_blocked); + KASSERT(p1 != NULL, ("contested mutex has no contesters")); + KASSERT(p != NULL, ("curproc is NULL for contested mutex")); + m->mtx_lock = (u_int64_t)p | MTX_CONTESTED; + if (p1->p_priority < p->p_priority) { + SET_PRIO(p, p1->p_priority); + } + mtx_exit(&sched_lock, MTX_SPIN); + return; + } + /* + * If the mutex isn't already contested and + * a failure occurs setting the contested bit the + * mutex was either release or the + * state of the RECURSION bit changed. + */ + if ((v & MTX_CONTESTED) == 0 && + !atomic_cmpset_64(&m->mtx_lock, v, + v | MTX_CONTESTED)) { + mtx_exit(&sched_lock, MTX_SPIN); + continue; + } + + /* We definitely have to sleep for this lock */ + mtx_assert(m, MA_NOTOWNED); + +#ifdef notyet + /* + * If we're borrowing an interrupted thread's VM + * context must clean up before going to sleep. + */ + if (p->p_flag & (P_ITHD | P_SITHD)) { + ithd_t *it = (ithd_t *)p; + + if (it->it_interrupted) { + CTR2(KTR_LOCK, + "mtx_enter: 0x%x interrupted 0x%x", + it, it->it_interrupted); + intr_thd_fixup(it); + } + } +#endif + + /* Put us on the list of procs blocked on this mutex */ + if (TAILQ_EMPTY(&m->mtx_blocked)) { + p1 = (struct proc *)(m->mtx_lock & + MTX_FLAGMASK); + LIST_INSERT_HEAD(&p1->p_contested, m, + mtx_contested); + TAILQ_INSERT_TAIL(&m->mtx_blocked, p, p_procq); + } else { + TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) + if (p1->p_priority > p->p_priority) + break; + if (p1) + TAILQ_INSERT_BEFORE(p1, p, p_procq); + else + TAILQ_INSERT_TAIL(&m->mtx_blocked, p, + p_procq); + } + + p->p_blocked = m; /* Who we're blocked on */ + p->p_stat = SMTX; +#if 0 + propagate_priority(p); +#endif + CTR3(KTR_LOCK, "mtx_enter: p 0x%p blocked on [0x%p] %s", + p, m, m->mtx_description); + mi_switch(); + CTR3(KTR_LOCK, + "mtx_enter: p 0x%p free from blocked on [0x%p] %s", + p, m, m->mtx_description); + mtx_exit(&sched_lock, MTX_SPIN); + } + ia64_mf(); + return; + case MTX_SPIN: + case MTX_SPIN | MTX_FIRST: + case MTX_SPIN | MTX_TOPHALF: + { + int i = 0; + + if (m->mtx_lock == (u_int64_t)p) { + m->mtx_recurse++; + return; + } + CTR1(KTR_LOCK, "mtx_enter: %p spinning", m); + for (;;) { + if (atomic_cmpset_64(&m->mtx_lock, MTX_UNOWNED, + (u_int64_t)p)) { + ia64_mf(); + break; + } + while (m->mtx_lock != MTX_UNOWNED) { + if (i++ < 1000000) + continue; + if (i++ < 6000000) + DELAY (1); +#ifdef DDB + else if (!db_active) +#else + else +#endif + panic( + "spin lock %s held by 0x%lx for > 5 seconds", + m->mtx_description, m->mtx_lock); + } + } + +#ifdef SMP_DEBUG + if (type != MTX_SPIN) + m->mtx_saveipl = 0xbeefface; + else +#endif + m->mtx_savepsr = psr; + CTR1(KTR_LOCK, "mtx_enter: 0x%p spin done", m); + return; + } + } +} + +void +mtx_exit_hard(struct mtx *m, int type) +{ + struct proc *p, *p1; + struct mtx *m1; + int pri; + + switch (type) { + case MTX_DEF: + case MTX_DEF | MTX_NOSWITCH: + if (m->mtx_recurse != 0) { + if (--(m->mtx_recurse) == 0) + atomic_clear_64(&m->mtx_lock, MTX_RECURSE); + CTR1(KTR_LOCK, "mtx_exit: 0x%p unrecurse", m); + return; + } + mtx_enter(&sched_lock, MTX_SPIN); + CTR1(KTR_LOCK, "mtx_exit: 0x%p contested", m); + p = CURPROC; + p1 = TAILQ_FIRST(&m->mtx_blocked); + MPASS(p->p_magic == P_MAGIC); + MPASS(p1->p_magic == P_MAGIC); + TAILQ_REMOVE(&m->mtx_blocked, p1, p_procq); + if (TAILQ_EMPTY(&m->mtx_blocked)) { + LIST_REMOVE(m, mtx_contested); + atomic_cmpset_64(&m->mtx_lock, m->mtx_lock, + MTX_UNOWNED); + CTR1(KTR_LOCK, "mtx_exit: 0x%p not held", m); + } else + m->mtx_lock = MTX_CONTESTED; + pri = MAXPRI; + LIST_FOREACH(m1, &p->p_contested, mtx_contested) { + int cp = TAILQ_FIRST(&m1->mtx_blocked)->p_priority; + if (cp < pri) + pri = cp; + } + if (pri > p->p_nativepri) + pri = p->p_nativepri; + SET_PRIO(p, pri); + CTR2(KTR_LOCK, "mtx_exit: 0x%p contested setrunqueue 0x%p", + m, p1); + p1->p_blocked = NULL; + p1->p_stat = SRUN; + setrunqueue(p1); + if ((type & MTX_NOSWITCH) == 0 && p1->p_priority < pri) { +#ifdef notyet + if (p->p_flag & (P_ITHD | P_SITHD)) { + ithd_t *it = (ithd_t *)p; + + if (it->it_interrupted) { + CTR2(KTR_LOCK, + "mtx_exit: 0x%x interruped 0x%x", + it, it->it_interrupted); + intr_thd_fixup(it); + } + } +#endif + setrunqueue(p); + CTR2(KTR_LOCK, "mtx_exit: 0x%p switching out lock=0x%lx", + m, m->mtx_lock); + mi_switch(); + CTR2(KTR_LOCK, "mtx_exit: 0x%p resuming lock=0x%lx", + m, m->mtx_lock); + } + mtx_exit(&sched_lock, MTX_SPIN); + return; + case MTX_SPIN: + case MTX_SPIN | MTX_FIRST: + if (m->mtx_recurse != 0) { + m->mtx_recurse--; + return; + } + ia64_mf(); + if (atomic_cmpset_64(&m->mtx_lock, CURTHD, MTX_UNOWNED)) { + if (type & MTX_FIRST) + enable_intr(); /* XXX is this kosher? */ + else { + MPASS(m->mtx_saveipl != 0xbeefface); + restore_intr(m->mtx_savepsr); + } + return; + } + panic("unsucuessful release of spin lock"); + case MTX_SPIN | MTX_TOPHALF: + if (m->mtx_recurse != 0) { + m->mtx_recurse--; + return; + } + ia64_mf(); + if (atomic_cmpset_64(&m->mtx_lock, CURTHD, MTX_UNOWNED)) + return; + panic("unsucuessful release of spin lock"); + default: + panic("mtx_exit_hard: unsupported type 0x%x\n", type); + } +} + +#define MV_DESTROY 0 /* validate before destory */ +#define MV_INIT 1 /* validate before init */ + +#ifdef SMP_DEBUG + +int mtx_validate __P((struct mtx *, int)); + +int +mtx_validate(struct mtx *m, int when) +{ + struct mtx *mp; + int i; + int retval = 0; + + if (m == &all_mtx || cold) + return 0; + + mtx_enter(&all_mtx, MTX_DEF); + ASS(kernacc((caddr_t)all_mtx.mtx_next, 4, 1) == 1); + ASS(all_mtx.mtx_next->mtx_prev == &all_mtx); + for (i = 0, mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) { + if (kernacc((caddr_t)mp->mtx_next, 4, 1) != 1) { + panic("mtx_validate: mp=%p mp->mtx_next=%p", + mp, mp->mtx_next); + } + i++; + if (i > mtx_cur_cnt) { + panic("mtx_validate: too many in chain, known=%d\n", + mtx_cur_cnt); + } + } + ASS(i == mtx_cur_cnt); + switch (when) { + case MV_DESTROY: + for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) + if (mp == m) + break; + ASS(mp == m); + break; + case MV_INIT: + for (mp = all_mtx.mtx_next; mp != &all_mtx; mp = mp->mtx_next) + if (mp == m) { + /* + * Not good. This mutex already exits + */ + retval = 1; +#if 1 + printf("re-initing existing mutex %s\n", + m->mtx_description); + ASS(m->mtx_lock == MTX_UNOWNED); + retval = 1; +#else + panic("re-initing existing mutex %s", + m->mtx_description); +#endif + } + } + mtx_exit(&all_mtx, MTX_DEF); + return (retval); +} +#endif + +void +mtx_init(struct mtx *m, char *t, int flag) +{ + + CTR2(KTR_LOCK, "mtx_init 0x%p (%s)", m, t); +#ifdef SMP_DEBUG + if (mtx_validate(m, MV_INIT)) /* diagnostic and error correction */ + return; +#endif + bzero((void *)m, sizeof *m); + TAILQ_INIT(&m->mtx_blocked); + m->mtx_description = t; + m->mtx_lock = MTX_UNOWNED; + /* Put on all mutex queue */ + mtx_enter(&all_mtx, MTX_DEF); + m->mtx_next = &all_mtx; + m->mtx_prev = all_mtx.mtx_prev; + m->mtx_prev->mtx_next = m; + all_mtx.mtx_prev = m; + if (++mtx_cur_cnt > mtx_max_cnt) + mtx_max_cnt = mtx_cur_cnt; + mtx_exit(&all_mtx, MTX_DEF); + witness_init(m, flag); +} + +void +mtx_destroy(struct mtx *m) +{ + + CTR2(KTR_LOCK, "mtx_destroy 0x%p (%s)", m, m->mtx_description); +#ifdef SMP_DEBUG + if (m->mtx_next == NULL) + panic("mtx_destroy: %p (%s) already destroyed", + m, m->mtx_description); + + if (!mtx_owned(m)) { + ASS(m->mtx_lock == MTX_UNOWNED); + } else { + ASS((m->mtx_lock & (MTX_RECURSE|MTX_CONTESTED)) == 0); + } + mtx_validate(m, MV_DESTROY); /* diagnostic */ +#endif + +#ifdef WITNESS + if (m->mtx_witness) + witness_destroy(m); +#endif /* WITNESS */ + + /* Remove from the all mutex queue */ + mtx_enter(&all_mtx, MTX_DEF); + m->mtx_next->mtx_prev = m->mtx_prev; + m->mtx_prev->mtx_next = m->mtx_next; +#ifdef SMP_DEBUG + m->mtx_next = m->mtx_prev = NULL; +#endif + mtx_cur_cnt--; + mtx_exit(&all_mtx, MTX_DEF); +} + +void +cpu_switch() +{ + struct proc *p = curproc; + + if (savectx(&p->p_addr->u_pcb)) + return; + + p = chooseproc(); + curproc = p; + restorectx(&p->p_addr->u_pcb); +} diff --git a/sys/ia64/ia64/sys_machdep.c b/sys/ia64/ia64/sys_machdep.c new file mode 100644 index 0000000..84e7620 --- /dev/null +++ b/sys/ia64/ia64/sys_machdep.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91 + * $FreeBSD$ + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <sys/lock.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +#include <sys/user.h> + +#include <machine/cpu.h> +#include <machine/sysarch.h> + +#include <vm/vm_kern.h> /* for kernel_map */ + +#include <machine/fpu.h> + +#ifndef _SYS_SYSPROTO_H_ +struct sysarch_args { + int op; + char *parms; +}; +#endif + +int +sysarch(p, uap) + struct proc *p; + register struct sysarch_args *uap; +{ + int error = 0; + + switch(SCARG(uap,op)) { + default: + error = EINVAL; + break; + } + return (error); +} diff --git a/sys/ia64/ia64/timerreg.h b/sys/ia64/ia64/timerreg.h new file mode 100644 index 0000000..0bfd7fc --- /dev/null +++ b/sys/ia64/ia64/timerreg.h @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp + * $FreeBSD$ + */ + +/* + * + * Register definitions for the Intel 8253 Programmable Interval Timer. + * + * This chip has three independent 16-bit down counters that can be + * read on the fly. There are three mode registers and three countdown + * registers. The countdown registers are addressed directly, via the + * first three I/O ports. The three mode registers are accessed via + * the fourth I/O port, with two bits in the mode byte indicating the + * register. (Why are hardware interfaces always so braindead?). + * + * To write a value into the countdown register, the mode register + * is first programmed with a command indicating the which byte of + * the two byte register is to be modified. The three possibilities + * are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then + * msb (TMR_MR_BOTH). + * + * To read the current value ("on the fly") from the countdown register, + * you write a "latch" command into the mode register, then read the stable + * value from the corresponding I/O port. For example, you write + * TMR_MR_LATCH into the corresponding mode register. Presumably, + * after doing this, a write operation to the I/O port would result + * in undefined behavior (but hopefully not fry the chip). + * Reading in this manner has no side effects. + * + * [IBM-PC] + * The outputs of the three timers are connected as follows: + * + * timer 0 -> irq 0 + * timer 1 -> dma chan 0 (for dram refresh) + * timer 2 -> speaker (via keyboard controller) + * + * Timer 0 is used to call hardclock. + * Timer 2 is used to generate console beeps. + * + * [PC-9801] + * The outputs of the three timers are connected as follows: + * + * timer 0 -> irq 0 + * timer 1 -> speaker (via keyboard controller) + * timer 2 -> RS232C + * + * Timer 0 is used to call hardclock. + * Timer 1 is used to generate console beeps. + */ + +/* + * Macros for specifying values to be written into a mode register. + */ +#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */ +#ifdef PC98 +#define TIMER_CNTR1 0x3fdb /* timer 1 counter port */ +#define TIMER_CNTR2 (IO_TIMER1 + 4) /* timer 2 counter port */ +#define TIMER_MODE (IO_TIMER1 + 6) /* timer mode port */ +#else +#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */ +#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */ +#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */ +#endif +#define TIMER_SEL0 0x00 /* select counter 0 */ +#define TIMER_SEL1 0x40 /* select counter 1 */ +#define TIMER_SEL2 0x80 /* select counter 2 */ +#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */ +#define TIMER_ONESHOT 0x02 /* mode 1, one shot */ +#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */ +#define TIMER_SQWAVE 0x06 /* mode 3, square wave */ +#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */ +#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */ +#define TIMER_LATCH 0x00 /* latch counter for reading */ +#define TIMER_LSB 0x10 /* r/w counter LSB */ +#define TIMER_MSB 0x20 /* r/w counter MSB */ +#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */ +#define TIMER_BCD 0x01 /* count in BCD */ + diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c new file mode 100644 index 0000000..1c66e63 --- /dev/null +++ b/sys/ia64/ia64/trap.c @@ -0,0 +1,782 @@ +/* $FreeBSD$ */ +/* From: src/sys/alpha/alpha/trap.c,v 1.33 */ +/* $NetBSD: trap.c,v 1.31 1998/03/26 02:21:46 thorpej Exp $ */ + +/* + * 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 "opt_ddb.h" +#include "opt_ktrace.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <machine/mutex.h> +#include <sys/ktr.h> +#include <sys/sysproto.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/exec.h> +#include <sys/lock.h> +#include <sys/vmmeter.h> +#include <sys/sysent.h> +#include <sys/syscall.h> +#include <sys/pioctl.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> +#include <vm/vm_param.h> +#include <sys/user.h> +#include <sys/ptrace.h> +#include <machine/clock.h> +#include <machine/md_var.h> +#include <machine/reg.h> +#include <machine/pal.h> +#include <machine/fpu.h> +#include <machine/smp.h> +#include <machine/mutex.h> + +#ifdef KTRACE +#include <sys/uio.h> +#include <sys/ktrace.h> +#endif + +#ifdef DDB +#include <ddb/ddb.h> +#endif + +u_int32_t want_resched; + +static int unaligned_fixup(struct trapframe *framep, struct proc *p); + +/* + * Define the code needed before returning to user mode, for + * trap and syscall. + */ +static int +userret(register struct proc *p, u_int64_t pc, u_quad_t oticks, int have_giant) +{ + int sig, s; + + /* take pending signals */ + while ((sig = CURSIG(p)) != 0) { + if (have_giant == 0) { + mtx_enter(&Giant, MTX_DEF); + have_giant = 1; + } + postsig(sig); + } + p->p_priority = p->p_usrpri; + if (want_resched) { + /* + * Since we are curproc, a clock interrupt could + * change our priority without changing run queues + * (the running process is not kept on a run queue). + * If this happened after we setrunqueue ourselves but + * before we switch()'ed, we might not be on the queue + * indicated by our priority. + */ + s = splstatclock(); + mtx_enter(&sched_lock, MTX_SPIN); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + mi_switch(); + mtx_exit(&sched_lock, MTX_SPIN); + splx(s); + while ((sig = CURSIG(p)) != 0) { + if (have_giant == 0) { + mtx_enter(&Giant, MTX_DEF); + have_giant = 1; + } + postsig(sig); + } + } + + /* + * If profiling, charge recent system time to the trapped pc. + */ + if (p->p_flag & P_PROFIL) { + if (have_giant == 0) { + mtx_enter(&Giant, MTX_DEF); + have_giant = 1; + } + addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); + } + + curpriority = p->p_priority; + return (have_giant); +} + +static const char *ia64_vector_names[] = { + "VHPT Translation", /* 0 */ + "Instruction TLB", /* 1 */ + "Data TLB", /* 2 */ + "Alternate Instruction TLB", /* 3 */ + "Alternate Data TLB", /* 4 */ + "Data Nested TLB", /* 5 */ + "Instruction Key Miss", /* 6 */ + "Data Key Miss", /* 7 */ + "Dirty-Bit", /* 8 */ + "Instruction Access-Bit", /* 9 */ + "Data Access-Bit", /* 10 */ + "Break Instruction", /* 11 */ + "External Interrupt", /* 12 */ + "Reserved 13", /* 13 */ + "Reserved 14", /* 14 */ + "Reserved 15", /* 15 */ + "Reserved 16", /* 16 */ + "Reserved 17", /* 17 */ + "Reserved 18", /* 18 */ + "Reserved 19", /* 19 */ + "Page Not Present", /* 20 */ + "Key Permission", /* 21 */ + "Instruction Access Rights", /* 22 */ + "Data Access Rights", /* 23 */ + "General Exception", /* 24 */ + "Disabled FP-Register", /* 25 */ + "NaT Consumption", /* 26 */ + "Speculation", /* 27 */ + "Reserved 28", /* 28 */ + "Debug", /* 29 */ + "Unaligned Reference", /* 30 */ + "Unsupported Data Reference", /* 31 */ + "Floating-point Fault", /* 32 */ + "Floating-point Trap", /* 33 */ + "Lower-Privilege Transfer Trap", /* 34 */ + "Taken Branch Trap", /* 35 */ + "Single Step Trap", /* 36 */ + "Reserved 37", /* 37 */ + "Reserved 38", /* 38 */ + "Reserved 39", /* 39 */ + "Reserved 40", /* 40 */ + "Reserved 41", /* 41 */ + "Reserved 42", /* 42 */ + "Reserved 43", /* 43 */ + "Reserved 44", /* 44 */ + "IA-32 Exception", /* 45 */ + "IA-32 Intercept", /* 46 */ + "IA-32 Interrupt", /* 47 */ + "Reserved 48", /* 48 */ + "Reserved 49", /* 49 */ + "Reserved 50", /* 50 */ + "Reserved 51", /* 51 */ + "Reserved 52", /* 52 */ + "Reserved 53", /* 53 */ + "Reserved 54", /* 54 */ + "Reserved 55", /* 55 */ + "Reserved 56", /* 56 */ + "Reserved 57", /* 57 */ + "Reserved 58", /* 58 */ + "Reserved 59", /* 59 */ + "Reserved 60", /* 60 */ + "Reserved 61", /* 61 */ + "Reserved 62", /* 62 */ + "Reserved 63", /* 63 */ + "Reserved 64", /* 64 */ + "Reserved 65", /* 65 */ + "Reserved 66", /* 66 */ + "Reserved 67", /* 67 */ +}; + +static void +printtrap(int vector, struct trapframe *framep, int isfatal, int user) +{ + printf("\n"); + printf("%s %s trap:\n", isfatal? "fatal" : "handled", + user ? "user" : "kernel"); + printf("\n"); + printf(" trap vector = 0x%x (%s)\n", + vector, ia64_vector_names[vector]); + printf(" iip = 0x%lx\n", framep->tf_cr_iip); + printf(" ipsr = 0x%lx\n", framep->tf_cr_ipsr); + printf(" isr = 0x%lx\n", framep->tf_cr_isr); + printf(" ifa = 0x%lx\n", framep->tf_cr_ifa); + printf(" curproc = %p\n", curproc); + if (curproc != NULL) + printf(" pid = %d, comm = %s\n", curproc->p_pid, + curproc->p_comm); + printf("\n"); +} + +/* + * Trap is called from exception.s to handle most types of processor traps. + * System calls are broken out for efficiency and ASTs are broken out + * to make the code a bit cleaner and more representative of the + * architecture. + */ +/*ARGSUSED*/ +void +trap(int vector, struct trapframe *framep) +{ + register struct proc *p; + register int i; + u_int64_t ucode; + u_quad_t sticks; + int user; + +#if 0 + /* + * Find our per-cpu globals. + */ + globalp = (struct globaldata *) alpha_pal_rdval(); /* XXx */ +#endif + + cnt.v_trap++; + p = curproc; + ucode = 0; + + user = ((framep->tf_cr_ipsr & IA64_PSR_CPL) == IA64_PSR_CPL_USER); + if (user) { + sticks = p->p_sticks; + p->p_md.md_tf = framep; + } else { + sticks = 0; /* XXX bogus -Wuninitialized warning */ + } + + switch (vector) { + case IA64_VEC_UNALIGNED_REFERENCE: + /* + * If user-land, do whatever fixups, printing, and + * signalling is appropriate (based on system-wide + * and per-process unaligned-access-handling flags). + */ + if (user) { + mtx_enter(&Giant, MTX_DEF); + if ((i = unaligned_fixup(framep, p)) == 0) { + mtx_exit(&Giant, MTX_DEF); + goto out; + } + mtx_exit(&Giant, MTX_DEF); + ucode = framep->tf_cr_ifa; /* VA */ + break; + } + + /* + * Unaligned access from kernel mode is always an error, + * EVEN IF A COPY FAULT HANDLER IS SET! + * + * It's an error if a copy fault handler is set because + * the various routines which do user-initiated copies + * do so in a bcopy-like manner. In other words, the + * kernel never assumes that pointers provided by the + * user are properly aligned, and so if the kernel + * does cause an unaligned access it's a kernel bug. + */ + goto dopanic; + + case IA64_VEC_FLOATING_POINT_FAULT: + case IA64_VEC_FLOATING_POINT_TRAP: + /* + * If user-land, give a SIGFPE if software completion + * is not requested or if the completion fails. + */ + if (user) { + i = SIGFPE; + ucode = /*a0*/ 0; /* exception summary */ + break; + } + + /* Always fatal in kernel. Should never happen. */ + goto dopanic; + + case IA64_VEC_BREAK: + /* + * This should never happen. Breaks enter the kernel + * via break(). + */ + goto dopanic; + + + case IA64_VEC_DISABLED_FP: + /* + * on exit from the kernel, if proc == fpcurproc, + * FP is enabled. + */ + if (fpcurproc == p) { + printf("trap: fp disabled for fpcurproc == %p", p); + goto dopanic; + } + + ia64_fpstate_switch(p); + goto out; + break; + + case IA64_VEC_PAGE_NOT_PRESENT: + { + vm_offset_t va = framep->tf_cr_ifa; + struct vmspace *vm = NULL; + vm_map_t map; + vm_prot_t ftype = 0; + int rv; + + mtx_enter(&Giant, MTX_DEF); + /* + * If it was caused by fuswintr or suswintr, + * just punt. Note that we check the faulting + * address against the address accessed by + * [fs]uswintr, in case another fault happens + * when they are running. + */ + if (!user && + p != NULL && + p->p_addr->u_pcb.pcb_onfault == + (unsigned long)fswintrberr && + p->p_addr->u_pcb.pcb_accessaddr == va) { + framep->tf_cr_iip = p->p_addr->u_pcb.pcb_onfault; + p->p_addr->u_pcb.pcb_onfault = 0; + mtx_exit(&Giant, MTX_DEF); + goto out; + } + + /* + * It is only a kernel address space fault iff: + * 1. !user and + * 2. pcb_onfault not set or + * 3. pcb_onfault set but kernel space data fault + * The last can occur during an exec() copyin where the + * argument space is lazy-allocated. + * + * For the purposes of the Linux emulator, we allow + * kernel accesses to a small region of the + * user stack which the emulator uses to + * translate syscall arguments. + */ + if (!user + && ((va >= VM_MIN_KERNEL_ADDRESS) + || (p == NULL) + || (p->p_addr->u_pcb.pcb_onfault == 0))) { + if (va >= trunc_page(PS_STRINGS + - szsigcode + - SPARE_USRSPACE) + && va < round_page(PS_STRINGS + - szsigcode)) { + vm = p->p_vmspace; + map = &vm->vm_map; + } else { + map = kernel_map; + } + } else { + vm = p->p_vmspace; + map = &vm->vm_map; + } + + if (framep->tf_cr_isr & (IA64_ISR_X | IA64_ISR_R)) + ftype = VM_PROT_READ; + else + ftype = VM_PROT_WRITE; + + va = trunc_page((vm_offset_t)va); + + if (map != kernel_map) { + /* + * Keep swapout from messing with us + * during thiscritical time. + */ + ++p->p_lock; + + /* + * Grow the stack if necessary + */ + /* grow_stack returns false only if va falls into + * a growable stack region and the stack growth + * fails. It returns true if va was not within + * a growable stack region, or if the stack + * growth succeeded. + */ + if (!grow_stack (p, va)) { + rv = KERN_FAILURE; + --p->p_lock; + goto nogo; + } + + + /* Fault in the user page: */ + rv = vm_fault(map, va, ftype, + (ftype & VM_PROT_WRITE) + ? VM_FAULT_DIRTY + : VM_FAULT_NORMAL); + + --p->p_lock; + } else { + /* + * Don't have to worry about process + * locking or stacks in the kernel. + */ + rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + } + + nogo:; + /* + * If this was a stack access we keep track of the + * maximum accessed stack size. Also, if vm_fault + * gets a protection failure it is due to accessing + * the stack region outside the current limit and + * we need to reflect that as an access error. + */ + if (map != kernel_map && + (caddr_t)va >= vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)USRSTACK) { + if (rv == KERN_SUCCESS) { + unsigned nss; + + nss = ia64_btop(round_page(USRSTACK - va)); + if (nss > vm->vm_ssize) + vm->vm_ssize = nss; + } else if (rv == KERN_PROTECTION_FAILURE) + rv = KERN_INVALID_ADDRESS; + } + if (rv == KERN_SUCCESS) { + mtx_exit(&Giant, MTX_DEF); + goto out; + } + + mtx_exit(&Giant, MTX_DEF); + ucode = va; + i = SIGSEGV; +#ifdef DEBUG + printtrap(vector, framep, 1, user); +#endif + break; + } + + default: + goto dopanic; + } + +#ifdef DEBUG + printtrap(vector, framep, 1, user); +#endif + trapsignal(p, i, ucode); +out: + if (user) { + if (userret(p, framep->tf_cr_iip, sticks, 0)) + mtx_exit(&Giant, MTX_DEF); + } + return; + +dopanic: + printtrap(vector, framep, 1, user); + + /* XXX dump registers */ + +#ifdef DDB + kdb_trap(vector, framep); +#endif + + panic("trap"); +} + +/* + * Process a system call. + * + * System calls are strange beasts. They are passed the syscall number + * in v0, and the arguments in the registers (as normal). They return + * an error flag in a3 (if a3 != 0 on return, the syscall had an error), + * and the return value (if any) in v0. + * + * The assembly stub takes care of moving the call number into a register + * we can get to, and moves all of the argument registers into their places + * in the trap frame. On return, it restores the callee-saved registers, + * a3, and v0 from the frame before returning to the user process. + */ +void +syscall(code, framep) + u_int64_t code; + struct trapframe *framep; +{ +#if 0 + struct sysent *callp; + struct proc *p; + int error = 0; + u_int64_t opc; + u_quad_t sticks; + u_int64_t args[10]; /* XXX */ + u_int hidden = 0, nargs; + + /* + * Find our per-cpu globals. + */ +#if 0 + globalp = (struct globaldata *) alpha_pal_rdval(); +#endif + mtx_enter(&Giant, MTX_DEF); + +#if notdef /* can't happen, ever. */ + if ((framep->tf_cr_ipsr & IA64_PSR_CPL) == IA64_PSR_CPL_KERN) + panic("syscall"); +#endif + + cnt.v_syscall++; + p = curproc; + p->p_md.md_tf = framep; + opc = framep->tf_cr_iip; + sticks = p->p_sticks; + +#ifdef DIAGNOSTIC + alpha_fpstate_check(p); +#endif + + if (p->p_sysent->sv_prepsyscall) { + /* (*p->p_sysent->sv_prepsyscall)(framep, args, &code, ¶ms); */ + panic("prepsyscall"); + } else { + /* + * syscall() and __syscall() are handled the same on + * the ia64, as everything is 64-bit aligned, anyway. + */ + if (code == SYS_syscall || code == SYS___syscall) { + /* + * Code is first argument, followed by actual args. + */ + code = framep->tf_regs[FRAME_A0]; + hidden = 1; + } + } + + 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]; + + nargs = (callp->sy_narg & SYF_ARGMASK) + hidden; + switch (nargs) { + default: + if (nargs > 10) /* XXX */ + panic("syscall: too many args (%d)", nargs); + error = copyin((caddr_t)(alpha_pal_rdusp()), &args[6], + (nargs - 6) * sizeof(u_int64_t)); + case 6: + args[5] = framep->tf_regs[FRAME_A5]; + case 5: + args[4] = framep->tf_regs[FRAME_A4]; + case 4: + args[3] = framep->tf_regs[FRAME_A3]; + case 3: + args[2] = framep->tf_regs[FRAME_A2]; + case 2: + args[1] = framep->tf_regs[FRAME_A1]; + case 1: + args[0] = framep->tf_regs[FRAME_A0]; + case 0: + break; + } +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, (callp->sy_narg & SYF_ARGMASK), args + hidden); +#endif + if (error == 0) { + p->p_retval[0] = 0; + p->p_retval[1] = 0; + + STOPEVENT(p, S_SCE, (callp->sy_narg & SYF_ARGMASK)); + + error = (*callp->sy_call)(p, args + hidden); + } + + + switch (error) { + case 0: + framep->tf_regs[FRAME_V0] = p->p_retval[0]; + framep->tf_regs[FRAME_A4] = p->p_retval[1]; + framep->tf_regs[FRAME_A3] = 0; + break; + case ERESTART: + framep->tf_regs[FRAME_PC] = opc; + break; + case EJUSTRETURN: + 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]; + } + framep->tf_regs[FRAME_V0] = error; + framep->tf_regs[FRAME_A3] = 1; + break; + } + + /* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + + userret(p, framep->tf_regs[FRAME_PC], sticks, 1); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, p->p_retval[0]); +#endif + + /* + * This works because errno is findable through the + * register set. If we ever support an emulation where this + * is not the case, this code will need to be revisited. + */ + STOPEVENT(p, S_SCX, code); + mtx_exit(&Giant, MTX_DEF); +#endif +} + +/* + * Process the tail end of a fork() for the child. + */ +void +child_return(p) + struct proc *p; +{ + int have_giant; + + /* + * Return values in the frame set by cpu_fork(). + */ + + have_giant = userret(p, p->p_md.md_tf->tf_cr_iip, 0, + mtx_owned(&Giant)); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) { + if (have_giant == 0) { + mtx_enter(&Giant, MTX_DEF); + have_giant = 1; + } + ktrsysret(p->p_tracep, SYS_fork, 0, 0); + } +#endif + + if (have_giant) + mtx_exit(&Giant, MTX_DEF); +} + +/* + * Process an asynchronous software trap. + * This is relatively easy. + */ +void +ast(framep) + struct trapframe *framep; +{ + register struct proc *p; + u_quad_t sticks; + + mtx_enter(&Giant, MTX_DEF); + + p = curproc; + sticks = p->p_sticks; + p->p_md.md_tf = framep; + + if ((framep->tf_cr_ipsr & IA64_PSR_CPL) != IA64_PSR_CPL_USER) + panic("ast and not user"); + + cnt.v_soft++; + + PCPU_SET(astpending, 0); + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + addupc_task(p, p->p_stats->p_prof.pr_addr, + p->p_stats->p_prof.pr_ticks); + } + + userret(p, framep->tf_cr_iip, sticks, 1); + + mtx_exit(&Giant, MTX_DEF); +} + +extern int ia64_unaligned_print, ia64_unaligned_fix; +extern int ia64_unaligned_sigbus; + +static int +unaligned_fixup(struct trapframe *framep, struct proc *p) +{ + vm_offset_t va = framep->tf_cr_ifa; + int doprint, dofix, dosigbus; + int signal, size = 0; + unsigned long uac; + + /* + * Figure out what actions to take. + */ + + if (p) + uac = p->p_md.md_flags & MDP_UAC_MASK; + else + uac = 0; + + doprint = ia64_unaligned_print && !(uac & MDP_UAC_NOPRINT); + dofix = ia64_unaligned_fix && !(uac & MDP_UAC_NOFIX); + dosigbus = ia64_unaligned_sigbus | (uac & MDP_UAC_SIGBUS); + + /* + * See if the user can access the memory in question. + * Even if it's an unknown opcode, SEGV if the access + * should have failed. + */ + if (!useracc((caddr_t)va, size ? size : 1, VM_PROT_WRITE)) { + signal = SIGSEGV; + goto out; + } + + /* + * If we're supposed to be noisy, squawk now. + */ + if (doprint) { + uprintf("pid %d (%s): unaligned access: va=0x%lx pc=0x%lx\n", + p->p_pid, p->p_comm, va, p->p_md.md_tf->tf_cr_iip); + } + + /* + * If we should try to fix it and know how, give it a shot. + * + * We never allow bad data to be unknowingly used by the + * user process. That is, if we decide not to fix up an + * access we cause a SIGBUS rather than letting the user + * process go on without warning. + * + * If we're trying to do a fixup, we assume that things + * will be botched. If everything works out OK, + * unaligned_{load,store}_* clears the signal flag. + */ + signal = SIGBUS; + if (dofix && size != 0) { + /* + * XXX not done yet. + */ + } + + /* + * Force SIGBUS if requested. + */ + if (dosigbus) + signal = SIGBUS; + +out: + return (signal); +} diff --git a/sys/ia64/ia64/vm_machdep.c b/sys/ia64/ia64/vm_machdep.c new file mode 100644 index 0000000..53682b7 --- /dev/null +++ b/sys/ia64/ia64/vm_machdep.c @@ -0,0 +1,494 @@ +/*- + * 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/vnode.h> +#include <sys/vmmeter.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/unistd.h> + +#include <machine/clock.h> +#include <machine/cpu.h> +#include <machine/fpu.h> +#include <machine/md_var.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <sys/lock.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +#include <sys/user.h> + +/* + * quick version of vm_fault + */ +int +vm_fault_quick(v, prot) + caddr_t v; + int prot; +{ + int r; + if (prot & VM_PROT_WRITE) + r = subyte(v, fubyte(v)); + else + r = fubyte(v); + return(r); +} + +/* + * 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(p1, p2, flags) + register struct proc *p1, *p2; + int flags; +{ + if ((flags & RFPROC) == 0) + return; + + p2->p_md.md_tf = p1->p_md.md_tf; + p2->p_md.md_flags = p1->p_md.md_flags & (MDP_FPUSED | MDP_UAC_MASK); + + /* + * Cache the physical address of the pcb, so we can + * swap to it easily. + */ + p2->p_md.md_pcbpaddr = (void*)vtophys((vm_offset_t)&p2->p_addr->u_pcb); + + /* + * Copy floating point state from the FP chip to the PCB + * if this process has state stored there. + */ + ia64_fpstate_save(p1, 0); + + /* + * Copy pcb and stack from proc p1 to p2. We do this as + * cheaply as possible, copying only the active part of the + * stack. The stack and pcb need to agree. Make sure that the + * new process has FEN disabled. + */ + p2->p_addr->u_pcb = p1->p_addr->u_pcb; +#if 0 + p2->p_addr->u_pcb.pcb_hw.apcb_usp = ia64_pal_rdusp(); + p2->p_addr->u_pcb.pcb_hw.apcb_flags &= ~IA64_PCB_FLAGS_FEN; +#endif + + /* + * Set the floating point state. + */ +#if 0 + if ((p2->p_addr->u_pcb.pcb_fp_control & IEEE_INHERIT) == 0) { + p2->p_addr->u_pcb.pcb_fp_control = 0; + p2->p_addr->u_pcb.pcb_fp.fpr_cr = (FPCR_DYN_NORMAL + | FPCR_INVD | FPCR_DZED + | FPCR_OVFD | FPCR_INED + | FPCR_UNFD); + } +#endif + + /* + * Arrange for a non-local goto when the new process + * is started, to resume here, returning nonzero from setjmp. + */ +#ifdef DIAGNOSTIC + if (p1 != curproc) + panic("cpu_fork: curproc"); + ia64_fpstate_check(p1); +#endif + + /* + * create the child's kernel stack, from scratch. + */ + { + struct user *up = p2->p_addr; + struct trapframe *p2tf; + + /* + * Pick a stack pointer, leaving room for a trapframe; + * copy trapframe from parent so return to user mode + * will be to right address, with correct registers. + */ + p2tf = p2->p_md.md_tf = (struct trapframe *) + ((char *)p2->p_addr + USPACE - sizeof(struct trapframe)); + bcopy(p1->p_md.md_tf, p2->p_md.md_tf, + sizeof(struct trapframe)); + + /* + * Set up return-value registers as fork() libc stub expects. + */ +#if 0 + p2tf->tf_regs[FRAME_V0] = 0; /* child's pid (linux) */ + p2tf->tf_regs[FRAME_A3] = 0; /* no error */ + p2tf->tf_regs[FRAME_A4] = 1; /* is child (FreeBSD) */ + + /* + * Arrange for continuation at child_return(), which + * will return to exception_return(). Note that the child + * process doesn't stay in the kernel for long! + * + * This is an inlined version of cpu_set_kpc. + */ + up->u_pcb.pcb_hw.apcb_ksp = (u_int64_t)p2tf; + up->u_pcb.pcb_context[0] = + (u_int64_t)child_return; /* s0: pc */ + up->u_pcb.pcb_context[1] = + (u_int64_t)exception_return; /* s1: ra */ + up->u_pcb.pcb_context[2] = (u_long) p2; /* s2: a0 */ + up->u_pcb.pcb_context[7] = + (u_int64_t)switch_trampoline; /* ra: assembly magic */ +#endif + } +} + +/* + * 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(p, func, arg) + struct proc *p; + void (*func) __P((void *)); + void *arg; +{ +#if 0 + /* + * Note that the trap frame follows the args, so the function + * is really called like this: func(arg, frame); + */ + p->p_addr->u_pcb.pcb_context[0] = (u_long) func; + p->p_addr->u_pcb.pcb_context[2] = (u_long) arg; +#endif +} + +/* + * cpu_exit is called as the last action during exit. + * We drop the fp state (if we have it) and switch to a live one. + * When the proc is reaped, cpu_wait() will gc the VM state. + */ +void +cpu_exit(p) + register struct proc *p; +{ + ia64_fpstate_drop(p); + + (void) splhigh(); + cnt.v_swtch++; + cpu_switch(); + panic("cpu_exit"); +} + +void +cpu_wait(p) + struct proc *p; +{ + /* drop per-process resources */ + pmap_dispose_proc(p); + + /* and clean-out the vmspace */ + vmspace_free(p->p_vmspace); +} + +/* + * Dump the machine specific header information at the start of a core dump. + */ +int +cpu_coredump(p, vp, cred) + struct proc *p; + struct vnode *vp; + struct ucred *cred; +{ + + return (vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES), + (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, + p)); +} + +#ifdef notyet +static void +setredzone(pte, vaddr) + u_short *pte; + caddr_t vaddr; +{ +/* eventually do this by setting up an expand-down stack segment + for ss0: selector, allowing stack access down to top of u. + this means though that protection violations need to be handled + thru a double fault exception that must do an integral task + switch to a known good context, within which a dump can be + taken. a sensible scheme might be to save the initial context + used by sched (that has physical memory mapped 1:1 at bottom) + and take the dump while still in mapped mode */ +} +#endif + +/* + * Map an IO request into kernel virtual address space. + * + * All requests are (re)mapped into kernel VA space. + * Notice that we use b_bufsize for the size of the buffer + * to be mapped. b_bcount might be modified by the driver. + */ +void +vmapbuf(bp) + register struct buf *bp; +{ + register caddr_t addr, v, kva; + vm_offset_t pa; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); + + for (v = bp->b_saveaddr, addr = (caddr_t)trunc_page(bp->b_data); + addr < bp->b_data + bp->b_bufsize; + addr += PAGE_SIZE, v += PAGE_SIZE) { + /* + * Do the vm_fault if needed; do the copy-on-write thing + * when reading stuff off device into memory. + */ + vm_fault_quick(addr, + (bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ); + pa = trunc_page(pmap_kextract((vm_offset_t) addr)); + if (pa == 0) + panic("vmapbuf: page not present"); + vm_page_hold(PHYS_TO_VM_PAGE(pa)); + pmap_kenter((vm_offset_t) v, pa); + } + + kva = bp->b_saveaddr; + bp->b_saveaddr = bp->b_data; + bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK); +} + +/* + * Free the io map PTEs associated with this IO operation. + * We also invalidate the TLB entries and restore the original b_addr. + */ +void +vunmapbuf(bp) + register struct buf *bp; +{ + register caddr_t addr; + vm_offset_t pa; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); + + for (addr = (caddr_t)trunc_page(bp->b_data); + addr < bp->b_data + bp->b_bufsize; + addr += PAGE_SIZE) { + pa = trunc_page(pmap_kextract((vm_offset_t) addr)); + pmap_kremove((vm_offset_t) addr); + vm_page_unhold(PHYS_TO_VM_PAGE(pa)); + } + + bp->b_data = bp->b_saveaddr; +} + +/* + * Force reset the processor by invalidating the entire address space! + */ +void +cpu_reset() +{ + /* prom_halt(0); */ +} + +int +grow_stack(p, sp) + struct proc *p; + size_t sp; +{ + int rv; + + rv = vm_map_growstack (p, sp); + if (rv != KERN_SUCCESS) + return (0); + + return (1); +} + + +static int cnt_prezero; + +SYSCTL_INT(_machdep, OID_AUTO, cnt_prezero, CTLFLAG_RD, &cnt_prezero, 0, ""); + +/* + * Implement the pre-zeroed page mechanism. + * This routine is called from the idle loop. + */ + +#define ZIDLE_LO(v) ((v) * 2 / 3) +#define ZIDLE_HI(v) ((v) * 4 / 5) + +int +vm_page_zero_idle() +{ + static int free_rover; + static int zero_state; + vm_page_t m; + int s; + + /* + * Attempt to maintain approximately 1/2 of our free pages in a + * PG_ZERO'd state. Add some hysteresis to (attempt to) avoid + * generally zeroing a page when the system is near steady-state. + * Otherwise we might get 'flutter' during disk I/O / IPC or + * fast sleeps. We also do not want to be continuously zeroing + * pages because doing so may flush our L1 and L2 caches too much. + */ + + if (zero_state && vm_page_zero_count >= ZIDLE_LO(cnt.v_free_count)) + return(0); + if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count)) + return(0); + +#ifdef SMP + if (try_mplock()) { +#endif + s = splvm(); + m = vm_page_list_find(PQ_FREE, free_rover, FALSE); + zero_state = 0; + if (m != NULL && (m->flags & PG_ZERO) == 0) { + vm_page_queues[m->queue].lcnt--; + TAILQ_REMOVE(&vm_page_queues[m->queue].pl, m, pageq); + m->queue = PQ_NONE; + splx(s); +#if 0 + rel_mplock(); +#endif + pmap_zero_page(VM_PAGE_TO_PHYS(m)); +#if 0 + get_mplock(); +#endif + (void)splvm(); + vm_page_flag_set(m, PG_ZERO); + m->queue = PQ_FREE + m->pc; + vm_page_queues[m->queue].lcnt++; + TAILQ_INSERT_TAIL(&vm_page_queues[m->queue].pl, m, + pageq); + ++vm_page_zero_count; + ++cnt_prezero; + if (vm_page_zero_count >= ZIDLE_HI(cnt.v_free_count)) + zero_state = 1; + } + free_rover = (free_rover + PQ_PRIME2) & PQ_L2_MASK; + splx(s); +#ifdef SMP + rel_mplock(); +#endif + return (1); +#ifdef SMP + } +#endif + return (0); +} + +/* + * Software interrupt handler for queued VM system processing. + */ +void +swi_vm() +{ +#if 0 + 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; +} diff --git a/sys/ia64/include/_limits.h b/sys/ia64/include/_limits.h new file mode 100644 index 0000000..99ca2d8 --- /dev/null +++ b/sys/ia64/include/_limits.h @@ -0,0 +1,96 @@ +/* $FreeBSD$ */ +/* From: NetBSD: limits.h,v 1.3 1997/04/06 08:47:31 cgd Exp */ + +/* + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#define CHAR_BIT 8 /* number of bits in a char */ +#define MB_LEN_MAX 6 /* Allow 31 bit UTF2 */ + +/* + * 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 and LONG_MIN is so the value is not unsigned; 2147483648 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + * These numbers work for pcc as well. The UINT_MAX and ULONG_MAX values + * are written as hex so that GCC will be quiet about large integer constants. + */ +#define SCHAR_MAX 0x7f /* max value for a signed char */ +#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */ + +#define UCHAR_MAX 0xffU /* max value for an unsigned char */ +#define CHAR_MAX 0x7f /* max value for a char */ +#define CHAR_MIN (-0x7f-1) /* min value for a char */ + +#define USHRT_MAX 0xffffU /* 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 */ + +#define ULONG_MAX 0xffffffffffffffffUL /* max for an unsigned long */ +#define LONG_MAX 0x7fffffffffffffffL /* max for a long */ +#define LONG_MIN (-0x7fffffffffffffffL-1) /* min for a long */ + +#if !defined(_ANSI_SOURCE) +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t */ + +/* Quads and longs are the same on the alpha */ +#define UQUAD_MAX (ULONG_MAX) /* max value for a uquad_t */ +#define QUAD_MAX (LONG_MAX) /* max value for a quad_t */ +#define QUAD_MIN (LONG_MIN) /* min value for a quad_t */ + +#endif /* !_POSIX_SOURCE && !_XOPEN_SOURCE */ +#endif /* !_ANSI_SOURCE */ + +#if (!defined(_ANSI_SOURCE)&&!defined(_POSIX_SOURCE)) || defined(_XOPEN_SOURCE) +#define LONG_BIT 64 +#define WORD_BIT 32 + +#define DBL_DIG 15 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MIN 2.2250738585072014E-308 + +#define FLT_DIG 6 +#define FLT_MAX 3.40282347E+38F +#define FLT_MIN 1.17549435E-38F +#endif diff --git a/sys/ia64/include/ansi.h b/sys/ia64/include/ansi.h new file mode 100644 index 0000000..c5ef23d --- /dev/null +++ b/sys/ia64/include/ansi.h @@ -0,0 +1,119 @@ +/* $FreeBSD$ */ +/* From: NetBSD: ansi.h,v 1.9 1997/11/23 20:20:53 kleink Exp */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _ANSI_H_ +#define _ANSI_H_ + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ int /* clock() */ +#define _BSD_PTRDIFF_T_ long /* ptr1 - ptr2 */ +#define _BSD_SIZE_T_ unsigned long /* sizeof() */ +#define _BSD_SSIZE_T_ long /* byte count or error */ +#define _BSD_TIME_T_ int /* time() */ +#define _BSD_VA_LIST_ __builtin_va_list /* va_list */ +#define _BSD_CLOCKID_T_ int /* clockid_t */ +#define _BSD_TIMER_T_ int /* timer_t */ +#define _BSD_SUSECONDS_T_ int /* suseconds_t */ +#define _BSD_USECONDS_T_ unsigned int /* useconds_t */ + +/* + * Types which are fundamental to the implementation and must be used + * in more than one standard header although they are only declared in + * one (perhaps nonstandard) header are defined here. Standard headers + * use _BSD_XXX_T_ without undef'ing it. + */ +#define _BSD_CT_RUNE_T_ int /* arg type for ctype funcs */ +#define _BSD_OFF_T_ long /* file offset */ +#define _BSD_PID_T_ int /* process [group] */ + +/* + * Runes (wchar_t) is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you + * lose a bit of ANSI conformance, but your programs will still work. + * + * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t + * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains + * defined for ctype.h. + */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_RUNE_T_ int /* rune_t */ + +/* + * Frequencies of the clock ticks reported by clock() and times(). They + * are the same as stathz for bogus historical reasons. They should be + * 1e6 because clock() and times() are implemented using getrusage() and + * there is no good reason why they should be less accurate. There is + * the bad reason that (broken) programs might not like clock_t or + * CLOCKS_PER_SEC being ``double'' (``unsigned long'' is not large enough + * to hold the required 24 hours worth of ticks if the frequency is + * 1000000ul, and ``unsigned long long'' would be nonstandard). + */ +#define _BSD_CLK_TCK_ 100 +#define _BSD_CLOCKS_PER_SEC_ 100 + +/* + * Internal names for basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +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; +typedef long __int64_t; +typedef unsigned long __uint64_t; + +typedef long __intptr_t; +typedef unsigned long __uintptr_t; + +#endif /* _ANSI_H_ */ diff --git a/sys/ia64/include/asm.h b/sys/ia64/include/asm.h new file mode 100644 index 0000000..4d20be3 --- /dev/null +++ b/sys/ia64/include/asm.h @@ -0,0 +1,257 @@ +/* $FreeBSD$ */ +/* From: NetBSD: asm.h,v 1.18 1997/11/03 04:22:06 ross Exp */ + +/* + * Copyright (c) 1991,1990,1989,1994,1995,1996 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. + */ + +/* + * Assembly coding style + * + * This file contains macros and register defines to + * aid in writing more readable assembly code. + * Some rules to make assembly code understandable by + * a debugger are also noted. + * + * The document + * + * "ALPHA Calling Standard", DEC 27-Apr-90 + * + * defines (a superset of) the rules and conventions + * we use. While we make no promise of adhering to + * such standard and its evolution (esp where we + * can get faster code paths) it is certainly intended + * that we be interoperable with such standard. + * + * In this sense, this file is a proper part of the + * definition of the (software) Alpha architecture. + */ + +/* + * Macro to make a local label name. + */ +#define LLABEL(name,num) L ## name ## num + +/* + * MCOUNT + */ + +#if !defined(GPROF) && !defined(PROF) +#define MCOUNT /* nothing */ +#else +#define MCOUNT \ + .set noat; \ + jsr at_reg,_mcount; \ + .set at +#endif + +/* + * LEAF + * Declare a global leaf function. + * A leaf function does not call other functions. + */ +#define LEAF(_name_, _n_args_) \ + .global _name_; \ + .proc _name_; \ +_name_:; \ + .regstk _n_args_, 0, 0, 0 \ + MCOUNT + +#define LEAF_NOPROFILE(_name_, _n_args_) \ + .global _name_; \ + .proc _name_; \ +_name_:; \ + .regstk _n_args_, 0, 0, 0 + +/* + * STATIC_LEAF + * Declare a local leaf function. + */ +#define STATIC_LEAF(_name_, _n_args_) \ + .proc _name_; \ +_name_:; \ + .regstk _n_args_, 0, 0, 0 \ + MCOUNT +/* + * XLEAF + * Global alias for a leaf function, or alternate entry point + */ +#define XLEAF(_name_) \ + .globl _name_; \ +_name_: + +/* + * STATIC_XLEAF + * Local alias for a leaf function, or alternate entry point + */ +#define STATIC_XLEAF(_name_) \ +_name_: + +/* + * NESTED + * Declare a (global) nested function + * A nested function calls other functions and needs + * to use alloc to save registers. + */ +#define NESTED(_name_,_n_args_,_n_locals_,_n_outputs_, \ + _pfs_reg_,_rp_reg_) \ + .globl _name_; \ + .proc _name_; \ +_name_:; \ + alloc _pfs_reg_=ar.pfs,_n_args_,_n_locals_,_n_outputs_,0;; \ + mov _rp_reg_=rp \ + MCOUNT + +#define NESTED_NOPROFILE(_name_,_n_args_,_n_locals_,_n_outputs_, \ + _pfs_reg_,_rp_reg_) \ + .globl _name_; \ + .proc _name_; \ +_name_:; \ + alloc _pfs_reg_=ar.pfs,_n_args_,_n_locals_,_n_outputs_,0;; \ + mov _rp_reg_=rp + +/* + * STATIC_NESTED + * Declare a local nested function. + */ +#define STATIC_NESTED(_name_,_n_args_,_n_locals_,_n_outputs_, \ + _pfs_reg_,_rp_reg_) \ + .proc _name_; \ +_name_:; \ + alloc _pfs_reg_=ar.pfs,_n_args_,_n_locals_,_n_outputs_,0;; \ + mov _rp_reg_=rp;; \ + MCOUNT + +/* + * XNESTED + * Same as XLEAF, for a nested function. + */ +#define XNESTED(_name_) \ + .globl _name_; \ +_name_: + + +/* + * STATIC_XNESTED + * Same as STATIC_XLEAF, for a nested function. + */ +#define STATIC_XNESTED(_name_) \ +_name_: + + +/* + * END + * Function delimiter + */ +#define END(_name_) \ + .endp _name_ + + +/* + * EXPORT + * Export a symbol + */ +#define EXPORT(_name_) \ + .global _name_; \ +_name_: + + +/* + * IMPORT + * Make an external name visible, typecheck the size + */ +#define IMPORT(_name_, _size_) \ + /* .extern _name_,_size_ */ + + +/* + * ABS + * Define an absolute symbol + */ +#define ABS(_name_, _value_) \ + .globl _name_; \ +_name_ = _value_ + + +/* + * BSS + * Allocate un-initialized space for a global symbol + */ +#define BSS(_name_,_numbytes_) \ + .comm _name_,_numbytes_ + + +/* + * MSG + * Allocate space for a message (a read-only ascii string) + */ +#define ASCIZ .asciz +#define MSG(msg,reg,label) \ + lda reg, label; \ + .data; \ +label: ASCIZ msg; \ + .text; + +/* + * System call glue. + */ +#define SYSCALLNUM(name) \ + SYS_ ## name + +#define CALLSYS_NOERROR(name) \ + mov r15=SYSCALLNUM(name); \ + break 0x100000 ;; + +/* + * WEAK_ALIAS: create a weak alias (ELF only). + */ +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif + +/* + * Kernel RCS ID tag and copyright macros + */ + +#ifdef _KERNEL + +#ifdef __ELF__ +#define __KERNEL_SECTIONSTRING(_sec, _str) \ + .section _sec ; .asciz _str ; .text +#else /* __ELF__ */ +#define __KERNEL_SECTIONSTRING(_sec, _str) \ + .data ; .asciz _str ; .align 3 ; .text +#endif /* __ELF__ */ + +#define __KERNEL_RCSID(_n, _s) __KERNEL_SECTIONSTRING(.ident, _s) +#define __KERNEL_COPYRIGHT(_n, _s) __KERNEL_SECTIONSTRING(.copyright, _s) + +#ifdef NO_KERNEL_RCSIDS +#undef __KERNEL_RCSID +#define __KERNEL_RCSID(_n, _s) /* nothing */ +#endif + +#endif /* _KERNEL */ diff --git a/sys/ia64/include/atomic.h b/sys/ia64/include/atomic.h new file mode 100644 index 0000000..a7b3e21 --- /dev/null +++ b/sys/ia64/include/atomic.h @@ -0,0 +1,190 @@ +/*- + * 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_ + +/* + * Various simple arithmetic on memory which is atomic in the presence + * of interrupts and SMP safe. + */ + +/* + * Everything is built out of cmpxchg. + */ +#define IA64_CMPXCHG(sz, sem, type, p, cmpval, newval) \ +({ \ + type _cmpval = cmpval; \ + type _newval = newval; \ + volatile type *_p = (volatile type *) p; \ + type _ret; \ + \ + __asm __volatile ( \ + "mov ar.ccv=%2;;\n\t" \ + "cmpxchg" #sz "." #sem " %0=%4,%3,ar.ccv\n\t" \ + : "=r" (_ret), "=m" (*_p) \ + : "r" (_cmpval), "r" (_newval), "m" (*_p) \ + : "memory"); \ + _ret; \ +}) + +/* + * Some common forms of cmpxch. + */ +static __inline u_int32_t +ia64_cmpxchg_acq_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) +{ + return IA64_CMPXCHG(4, acq, u_int32_t, p, cmpval, newval); +} + +static __inline u_int32_t +ia64_cmpxchg_rel_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) +{ + return IA64_CMPXCHG(4, rel, u_int32_t, p, cmpval, newval); +} + +static __inline u_int64_t +ia64_cmpxchg_acq_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) +{ + return IA64_CMPXCHG(8, acq, u_int64_t, p, cmpval, newval); +} + +static __inline u_int64_t +ia64_cmpxchg_rel_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) +{ + return IA64_CMPXCHG(8, rel, u_int64_t, p, cmpval, newval); +} + +/* + * Store with release semantics is used to release locks. + */ +static __inline void +ia64_st_rel_32(volatile u_int32_t* p, u_int32_t v) +{ + __asm __volatile ("st4.rel %0=%1" + : "=m" (*p) + : "r" (v) + : "memory"); +} + +static __inline void +ia64_st_rel_64(volatile u_int64_t* p, u_int64_t v) +{ + __asm __volatile ("st8.rel %0=%1" + : "=m" (*p) + : "r" (v) + : "memory"); +} + +#define IA64_ATOMIC(sz, type, name, op) \ + \ +static __inline void \ +atomic_##name(volatile type *p, type v) \ +{ \ + type old; \ + do { \ + old = *p; \ + } while (IA64_CMPXCHG(sz, acq, type, p, old, old op v) != old); \ +} + +IA64_ATOMIC(1, u_int8_t, set_8, |) +IA64_ATOMIC(2, u_int16_t, set_16, |) +IA64_ATOMIC(4, u_int32_t, set_32, |) +IA64_ATOMIC(8, u_int64_t, set_64, |) + +IA64_ATOMIC(1, u_int8_t, clear_8, &~) +IA64_ATOMIC(2, u_int16_t, clear_16, &~) +IA64_ATOMIC(4, u_int32_t, clear_32, &~) +IA64_ATOMIC(8, u_int64_t, clear_64, &~) + +IA64_ATOMIC(1, u_int8_t, add_8, +) +IA64_ATOMIC(2, u_int16_t, add_16, +) +IA64_ATOMIC(4, u_int32_t, add_32, +) +IA64_ATOMIC(8, u_int64_t, add_64, +) + +IA64_ATOMIC(1, u_int8_t, subtract_8, -) +IA64_ATOMIC(2, u_int16_t, subtract_16, -) +IA64_ATOMIC(4, u_int32_t, subtract_32, -) +IA64_ATOMIC(8, u_int64_t, subtract_64, -) + +#undef IA64_ATOMIC +#undef IA64_CMPXCHG + +#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_set_long atomic_set_64 +#define atomic_clear_long atomic_clear_64 +#define atomic_add_long atomic_add_64 +#define atomic_subtract_long atomic_subtract_64 + +/* + * 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 int +atomic_cmpset_32(volatile u_int32_t* p, u_int32_t cmpval, u_int32_t newval) +{ + return ia64_cmpxchg_acq_32(p, cmpval, newval) == cmpval; +} + +/* + * 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 int +atomic_cmpset_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) +{ + return ia64_cmpxchg_acq_64(p, cmpval, newval) == cmpval; +} + +#define atomic_cmpset_int atomic_cmpset_32 +#define atomic_cmpset_long atomic_cmpset_64 + +static __inline int +atomic_cmpset_ptr(volatile void *dst, void *exp, void *src) +{ + return atomic_cmpset_long((volatile u_long *)dst, + (u_long)exp, (u_long)src); +} + +#endif /* ! _MACHINE_ATOMIC_H_ */ diff --git a/sys/ia64/include/bootinfo.h b/sys/ia64/include/bootinfo.h new file mode 100644 index 0000000..86b7e7a --- /dev/null +++ b/sys/ia64/include/bootinfo.h @@ -0,0 +1,86 @@ +/* $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. + */ + +/* + * 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) __P((void)); /* 160: console getc pointer */ + void (*cnputc) __P((int)); /* 168: console putc pointer */ + void (*cnpollc) __P((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/ia64/include/bus.h b/sys/ia64/include/bus.h new file mode 100644 index 0000000..c054193 --- /dev/null +++ b/sys/ia64/include/bus.h @@ -0,0 +1,1173 @@ +/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by 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. + */ +/* $FreeBSD$ */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include <machine/cpufunc.h> + +/* + * To remain compatible with NetBSD's interface, default to both memio and + * pio when neither of them is defined. + */ +#if !defined(_MACHINE_BUS_PIO_H_) && !defined(_IA64_BUS_MEMIO_H_) +#define _MACHINE_BUS_PIO_H_ +#define _MACHINE_BUS_MEMIO_H_ +#endif + +/* + * Values for the ia64 bus space tag, not to be used directly by MI code. + */ +#define IA64_BUS_SPACE_IO 0 /* space is i/o space */ +#define IA64_BUS_SPACE_MEM 1 /* space is mem space */ + +/* + * Bus address and size types + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF +#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF +#define BUS_SPACE_MAXSIZE (64 * 1024) /* Maximum supported size */ +#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF +#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF +#define BUS_SPACE_MAXADDR 0xFFFFFFFF + +#define BUS_SPACE_UNRESTRICTED (~0) + +/* + * Access methods for bus resources and address space. + */ +typedef int bus_space_tag_t; +typedef u_long bus_space_handle_t; + +/* + * Map a region of device bus space into CPU virtual address space. + */ + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 + +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, + int flags, bus_space_handle_t *bshp); + +/* + * Unmap a region of device bus space. + */ + +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + +/* + * Get a new handle for a subregion of an already-mapped area of bus space. + */ + +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); + +/* + * Allocate a region of memory that is accessible to devices in bus space. + */ + +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); + +/* + * Free a region of bus space accessible memory. + */ + +void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); + +#if defined(_MACHINE_BUS_PIO_H_) || defined(_MACHINE_BUS_MEMIO_H_) + +/* + * 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 tag, + bus_space_handle_t handle, + bus_size_t offset); + +static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag, + bus_space_handle_t handle, + bus_size_t offset); + +static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag, + bus_space_handle_t handle, + bus_size_t offset); + +static __inline u_int8_t +bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t offset) +{ +#if defined (_MACHINE_BUS_PIO_H_) +#if defined (_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + return (inb(handle + offset)); +#endif +#if defined (_MACHINE_BUS_MEMIO_H_) + return (readb(handle + offset)); +#endif +} + +static __inline u_int16_t +bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t offset) +{ +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + return (inw(handle + offset)); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) + return (readw(handle + offset)); +#endif +} + +static __inline u_int32_t +bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t offset) +{ +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + return (inl(handle + offset)); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) + return (readl(handle + offset)); +#endif +} + +#if 0 /* Cause a link error for bus_space_read_8 */ +#define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! +#endif + +/* + * 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 tag, + bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, + size_t count); + +static __inline void bus_space_read_multi_2(bus_space_tag_t tag, + bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, + size_t count); + +static __inline void bus_space_read_multi_4(bus_space_tag_t tag, + bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, + size_t count); + +static __inline void +bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + *addr++ = inb(bsh + offset); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + *addr++ = readb(bsh + offset); +#endif +} + +static __inline void +bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + *addr++ = inw(baddr); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + *addr++ = readw(baddr); +#endif +} + +static __inline void +bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + *addr++ = inl(baddr); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + *addr++ = readl(baddr); +#endif +} + +#if 0 /* Cause a link error for bus_space_read_multi_8 */ +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! +#endif + +/* + * 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); + +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); + +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); + + +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) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) { + *addr++ = inb(baddr); + baddr += 1; + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) { + *addr++ = readb(baddr); + baddr += 1; + } +#endif +} + +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) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) { + *addr++ = inw(baddr); + baddr += 2; + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) { + *addr++ = readw(baddr); + baddr += 2; + } +#endif +} + +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) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) { + *addr++ = inl(baddr); + baddr += 4; + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) { + *addr++ = readb(baddr); + baddr += 4; + } +#endif +} + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! +#endif + +/* + * 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 tag, + bus_space_handle_t bsh, + bus_size_t offset, u_int8_t value); + +static __inline void bus_space_write_2(bus_space_tag_t tag, + bus_space_handle_t bsh, + bus_size_t offset, u_int16_t value); + +static __inline void bus_space_write_4(bus_space_tag_t tag, + bus_space_handle_t bsh, + bus_size_t offset, u_int32_t value); + +static __inline void +bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t value) +{ +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + outb(bsh + offset, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + writeb(bsh + offset, value); +#endif +} + +static __inline void +bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t value) +{ +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + outw(bsh + offset, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + writew(bsh + offset, value); +#endif +} + +static __inline void +bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t value) +{ +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + outl(bsh + offset, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + writel(bsh + offset, value); +#endif +} + +#if 0 /* Cause a link error for bus_space_write_8 */ +#define bus_space_write_8 !!! bus_space_write_8 not implemented !!! +#endif + +/* + * 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 tag, + bus_space_handle_t bsh, + bus_size_t offset, + const u_int8_t *addr, + size_t count); +static __inline void bus_space_write_multi_2(bus_space_tag_t tag, + bus_space_handle_t bsh, + bus_size_t offset, + const u_int16_t *addr, + size_t count); + +static __inline void bus_space_write_multi_4(bus_space_tag_t tag, + bus_space_handle_t bsh, + bus_size_t offset, + const u_int32_t *addr, + size_t count); + +static __inline void +bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + outb(baddr, *addr++); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + writeb(baddr, *addr++); +#endif +} + +static __inline void +bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + outw(baddr, *addr++); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + writew(baddr, *addr++); +#endif +} + +static __inline void +bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + outl(baddr, *addr++); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + writel(baddr, *addr++); +#endif +} + +#if 0 /* Cause a link error for bus_space_write_multi_8 */ +#define bus_space_write_multi_8(t, h, o, a, c) \ + !!! bus_space_write_multi_8 unimplemented !!! +#endif + +/* + * 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); +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); +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); + +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) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) { + outb(baddr, *addr++); + baddr += 1; + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) { + writeb(baddr, *addr++); + baddr += 1; + } +#endif +} + +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) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) { + outw(baddr, *addr++); + baddr += 2; + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) { + writew(baddr, *addr++); + baddr += 2; + } +#endif +} + +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) +{ + bus_addr_t baddr = bsh + offset; +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) { + outl(baddr, *addr++); + baddr += 4; + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) { + writel(baddr, *addr++); + baddr += 4; + } +#endif +} + +#if 0 /* Cause a link error for bus_space_write_region_8 */ +#define bus_space_write_region_8 \ + !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * 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 value, size_t count); +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 value, size_t count); +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 value, size_t count); + +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 value, size_t count) +{ + bus_addr_t addr = bsh + offset; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + outb(addr, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + writeb(addr, value); +#endif +} + +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 value, size_t count) +{ + bus_addr_t addr = bsh + offset; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + outw(addr, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + writew(addr, value); +#endif +} + +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 value, size_t count) +{ + bus_addr_t addr = bsh + offset; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + while (count--) + outl(addr, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + while (count--) + writel(addr, value); +#endif +} + +#if 0 /* Cause a link error for bus_space_set_multi_8 */ +#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! +#endif + +/* + * 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 value, + size_t count); +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 value, + size_t count); +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 value, + size_t count); + +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 value, size_t count) +{ + bus_addr_t addr = bsh + offset; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + for (; count != 0; count--, addr++) + outb(addr, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + for (; count != 0; count--, addr++) + writeb(addr, value); +#endif +} + +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 value, size_t count) +{ + bus_addr_t addr = bsh + offset; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + for (; count != 0; count--, addr += 2) + outw(addr, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + for (; count != 0; count--, addr += 2) + writew(addr, value); +#endif +} + +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 value, size_t count) +{ + bus_addr_t addr = bsh + offset; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + for (; count != 0; count--, addr += 4) + outl(addr, value); +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + for (; count != 0; count--, addr += 4) + writel(addr, value); +#endif +} + +#if 0 /* Cause a link error for bus_space_set_region_8 */ +#define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! +#endif + +/* + * 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. + */ + +static __inline void bus_space_copy_region_1(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); + +static __inline void bus_space_copy_region_2(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); + +static __inline void bus_space_copy_region_4(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); + +static __inline void +bus_space_copy_region_1(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) +{ + bus_addr_t addr1 = bsh1 + off1; + bus_addr_t addr2 = bsh2 + off2; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + { + if (addr1 >= addr2) { + /* src after dest: copy forward */ + for (; count != 0; count--, addr1++, addr2++) + outb(addr2, inb(addr1)); + } else { + /* dest after src: copy backwards */ + for (addr1 += (count - 1), addr2 += (count - 1); + count != 0; count--, addr1--, addr2--) + outb(addr2, inb(addr1)); + } + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + { + if (addr1 >= addr2) { + /* src after dest: copy forward */ + for (; count != 0; count--, addr1++, addr2++) + writeb(addr2, readb(addr1)); + } else { + /* dest after src: copy backwards */ + for (addr1 += (count - 1), addr2 += (count - 1); + count != 0; count--, addr1--, addr2--) + writeb(addr2, readb(addr1)); + } + } +#endif +} + +static __inline void +bus_space_copy_region_2(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) +{ + bus_addr_t addr1 = bsh1 + off1; + bus_addr_t addr2 = bsh2 + off2; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + { + if (addr1 >= addr2) { + /* src after dest: copy forward */ + for (; count != 0; count--, addr1 += 2, addr2 += 2) + outw(addr2, inw(addr1)); + } else { + /* dest after src: copy backwards */ + for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); + count != 0; count--, addr1 -= 2, addr2 -= 2) + outw(addr2, inw(addr1)); + } + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + { + if (addr1 >= addr2) { + /* src after dest: copy forward */ + for (; count != 0; count--, addr1 += 2, addr2 += 2) + writew(addr2, readw(addr1)); + } else { + /* dest after src: copy backwards */ + for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1); + count != 0; count--, addr1 -= 2, addr2 -= 2) + writew(addr2, readw(addr1)); + } + } +#endif +} + +static __inline void +bus_space_copy_region_4(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) +{ + bus_addr_t addr1 = bsh1 + off1; + bus_addr_t addr2 = bsh2 + off2; + +#if defined(_MACHINE_BUS_PIO_H_) +#if defined(_MACHINE_BUS_MEMIO_H_) + if (tag == IA64_BUS_SPACE_IO) +#endif + { + if (addr1 >= addr2) { + /* src after dest: copy forward */ + for (; count != 0; count--, addr1 += 4, addr2 += 4) + outl(addr2, inl(addr1)); + } else { + /* dest after src: copy backwards */ + for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); + count != 0; count--, addr1 -= 4, addr2 -= 4) + outl(addr2, inl(addr1)); + } + } +#endif +#if defined(_MACHINE_BUS_MEMIO_H_) +#if defined(_MACHINE_BUS_PIO_H_) + else +#endif + { + if (addr1 >= addr2) { + /* src after dest: copy forward */ + for (; count != 0; count--, addr1 += 4, addr2 += 4) + writel(addr2, readl(addr1)); + } else { + /* dest after src: copy backwards */ + for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1); + count != 0; count--, addr1 -= 4, addr2 -= 4) + writel(addr2, readl(addr1)); + } + } +#endif +} + +#endif /* defined(_MACHINE_BUS_PIO_H_) || defined(_MACHINE_BUS_MEMIO_H_) */ + +#if 0 /* Cause a link error for bus_space_copy_8 */ +#define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!! +#endif + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh, + * bus_size_t offset, bus_size_t len, int flags); + * + */ +#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, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t len, int flags) +{ + ia64_mf(); +} + + +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ +#define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */ +#define BUS_DMA_ISA 0x10 /* map memory for ISA dma */ +#define BUS_DMA_BUS2 0x20 /* placeholders for bus functions... */ +#define BUS_DMA_BUS3 0x40 +#define BUS_DMA_BUS4 0x80 + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; + +/* + * bus_dmasync_op_t + * + * Operations performed by bus_dmamap_sync(). + */ +typedef enum { + BUS_DMASYNC_PREREAD, + BUS_DMASYNC_POSTREAD, + BUS_DMASYNC_PREWRITE, + BUS_DMASYNC_POSTWRITE +} bus_dmasync_op_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the characteristics + * of how to perform DMA mappings. This structure encapsultes + * information concerning address and alignment restrictions, number + * of S/G segments, amount of data per S/G segment, etc. + */ +typedef struct bus_dma_tag *bus_dma_tag_t; + +/* + * bus_dmamap_t + * + * DMA mapping instance information. + */ +typedef struct bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +typedef struct bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +} bus_dma_segment_t; + +/* + * A function that returns 1 if the address cannot be accessed by + * a device and 0 if it can be. + */ +typedef int bus_dma_filter_t(void *, bus_addr_t); + +/* + * Allocate a device specific dma_tag encapsulating the constraints of + * the parent tag in addition to other restrictions specified: + * + * alignment: alignment for segments. + * boundary: Boundary that segments cannot cross. + * lowaddr: Low restricted address that cannot appear in a mapping. + * highaddr: High restricted address that cannot appear in a mapping. + * filtfunc: An optional function to further test if an address + * within the range of lowaddr and highaddr cannot appear + * in a mapping. + * filtfuncarg: An argument that will be passed to filtfunc in addition + * to the address to test. + * maxsize: Maximum mapping size supported by this tag. + * nsegments: Number of discontinuities allowed in maps. + * maxsegsz: Maximum size of a segment in the map. + * flags: Bus DMA flags. + * dmat: A pointer to set to a valid dma tag should the return + * value of this function indicate success. + */ +/* XXX Should probably allow specification of alignment */ +int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt, + bus_size_t boundary, bus_addr_t lowaddr, + bus_addr_t highaddr, bus_dma_filter_t *filtfunc, + void *filtfuncarg, bus_size_t maxsize, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat); + +int bus_dma_tag_destroy(bus_dma_tag_t dmat); + +/* + * 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); + +/* + * 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); + +/* + * 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); + +/* + * Free a piece of memory and it's allociated dmamap, that was allocated + * via bus_dmamem_alloc. + */ +void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); + +/* + * A function that processes a successfully loaded dma map or an error + * from a delayed load map. + */ +typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); + +/* + * 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); + +/* + * Perform a syncronization operation on the given map. + */ +void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); +#define bus_dmamap_sync(dmat, dmamap, op) \ + if ((dmamap) != NULL) \ + _bus_dmamap_sync(dmat, dmamap, op) + +/* + * Release the mapping held by map. + */ +void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); +#define bus_dmamap_unload(dmat, dmamap) \ + if ((dmamap) != NULL) \ + _bus_dmamap_unload(dmat, dmamap) + +#endif /* _MACHINE_BUS_H_ */ diff --git a/sys/ia64/include/bus_memio.h b/sys/ia64/include/bus_memio.h new file mode 100644 index 0000000..a3b5e9e --- /dev/null +++ b/sys/ia64/include/bus_memio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1997 Justin Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_BUS_MEMIO_H_ +#define _MACHINE_BUS_MEMIO_H_ +#endif /* _MACHINE_BUS_MEMIO_H_ */ diff --git a/sys/ia64/include/bus_pio.h b/sys/ia64/include/bus_pio.h new file mode 100644 index 0000000..00f6e3d --- /dev/null +++ b/sys/ia64/include/bus_pio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1997 Justin Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_BUS_PIO_H_ +#define _MACHINE_BUS_PIO_H_ +#endif /* _MACHINE_BUS_PIO_H_ */ diff --git a/sys/ia64/include/clock.h b/sys/ia64/include/clock.h new file mode 100644 index 0000000..a5f1b62 --- /dev/null +++ b/sys/ia64/include/clock.h @@ -0,0 +1,25 @@ +/* + * 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 + +extern int disable_rtc_set; +extern int wall_cmos_clock; +extern int adjkerntz; + +void DELAY __P((int usec)); +int sysbeep __P((int pitch, int period)); +int acquire_timer2 __P((int mode)); +int release_timer2 __P((void)); + +#endif + +#endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/ia64/include/clockvar.h b/sys/ia64/include/clockvar.h new file mode 100644 index 0000000..f13d1df --- /dev/null +++ b/sys/ia64/include/clockvar.h @@ -0,0 +1,53 @@ +/* $FreeBSD$ */ +/* $NetBSD: clockvar.h,v 1.4 1997/06/22 08:02:18 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995 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. + */ + +/* + * Definitions for cpu-independent clock handling for the alpha and pmax. + */ + +/* + * clocktime structure: + * + * structure passed to TOY clocks when setting them. broken out this + * way, so that the time_t -> field conversion can be shared. + */ +struct clocktime { + int year; /* year - 1900 */ + int mon; /* month (1 - 12) */ + int day; /* day (1 - 31) */ + int hour; /* hour (0 - 23) */ + int min; /* minute (0 - 59) */ + int sec; /* second (0 - 59) */ + int dow; /* day of week (0 - 6; 0 = Sunday) */ +}; + +#include "clock_if.h" + +void clockattach(device_t); diff --git a/sys/ia64/include/console.h b/sys/ia64/include/console.h new file mode 100644 index 0000000..fe7f10e --- /dev/null +++ b/sys/ia64/include/console.h @@ -0,0 +1,10 @@ +/* $FreeBSD$ */ + +#ifndef _MACHINE_CONSOLE_H_ +#define _MACHINE_CONSOLE_H_ + +#include <sys/fbio.h> +#include <sys/kbio.h> +#include <sys/consio.h> + +#endif /* !_MACHINE_CONSOLE_H_ */ diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h new file mode 100644 index 0000000..3da3331 --- /dev/null +++ b/sys/ia64/include/cpu.h @@ -0,0 +1,174 @@ +/* $FreeBSD$ */ +/* From: NetBSD: cpu.h,v 1.18 1997/09/23 23:17:49 mjacob Exp */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: cpu.h 1.16 91/03/25$ + * + * @(#)cpu.h 8.4 (Berkeley) 1/5/94 + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +/* + * Exported definitions unique to Alpha cpu support. + */ + +#include <machine/frame.h> + +/* + * Arguments to hardclock and gatherstats encapsulate the previous + * machine state in an opaque clockframe. One the Alpha, we use + * what we push on an interrupt (a trapframe). + */ +struct clockframe { + struct trapframe cf_tf; +}; +#define CLKF_USERMODE(framep) \ + (((framep)->cf_tf.tf_cr_ipsr & IA64_PSR_CPL) == IA64_PSR_CPL_USER) +#define CLKF_BASEPRI(framep) \ + (((framep)->cf_tf.tf_cr_ipsr & IA64_PSR_I) == 0) +#define CLKF_PC(framep) ((framep)->cf_tf.tf_cr_iip) +#define CLKF_INTR(framep) (intr_nesting_level >= 2) + +/* + * Preempt the current process if in interrupt from user mode, + * or after the current trap/syscall if in system mode. + */ +#define need_resched() do { want_resched = 1; aston(); } while (0) + +#define resched_wanted() want_resched + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the hp300, request an ast to send us + * through trap, marking the proc as needing a profiling tick. + */ +#define need_proftick(p) \ + do { (p)->p_flag |= P_OWEUPC; aston(); } while (0) + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +#define signotify(p) aston() + +#define aston() PCPU_SET(astpending, 1) + +#ifdef _KERNEL +extern u_int32_t intr_nesting_level; /* bookeeping only; counts sw intrs */ +extern u_int32_t want_resched; /* resched() was called */ +#endif + + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_ROOT_DEVICE 2 /* string: root device name */ +#define CPU_UNALIGNED_PRINT 3 /* int: print unaligned accesses */ +#define CPU_UNALIGNED_FIX 4 /* int: fix unaligned accesses */ +#define CPU_UNALIGNED_SIGBUS 5 /* int: SIGBUS unaligned accesses */ +#define CPU_BOOTED_KERNEL 6 /* string: booted kernel name */ +#define CPU_ADJKERNTZ 7 /* int: timezone offset (seconds) */ +#define CPU_DISRTCSET 8 /* int: disable resettodr() call */ +#define CPU_WALLCLOCK 9 /* int: indicates wall CMOS clock */ +#define CPU_MAXID 9 /* 9 valid machdep IDs */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ + { "root_device", CTLTYPE_STRING }, \ + { "unaligned_print", CTLTYPE_INT }, \ + { "unaligned_fix", CTLTYPE_INT }, \ + { "unaligned_sigbus", CTLTYPE_INT }, \ + { "booted_kernel", CTLTYPE_STRING }, \ + { "adjkerntz", CTLTYPE_INT }, \ + { "disable_rtc_set", CTLTYPE_INT }, \ + { "wall_cmos_clock", CTLTYPE_INT }, \ +} + +#ifdef _KERNEL + +struct pcb; +struct proc; +struct reg; +struct rpb; +struct trapframe; + +extern struct proc *fpcurproc; +extern struct rpb *hwrpb; +extern volatile int mc_expected, mc_received; + +void ast __P((struct trapframe *)); +int badaddr __P((void *, size_t)); +int badaddr_read __P((void *, size_t, void *)); +void child_return __P((struct proc *p)); +u_int64_t console_restart __P((u_int64_t, u_int64_t, u_int64_t)); +void do_sir __P((void)); +void dumpconf __P((void)); +void exception_return __P((void)); /* MAGIC */ +void frametoreg __P((struct trapframe *, struct reg *)); +long fswintrberr __P((void)); /* MAGIC */ +int ia64_pa_access __P((u_long)); +void ia64_init __P((void)); +void ia64_fpstate_check __P((struct proc *p)); +void ia64_fpstate_save __P((struct proc *p, int write)); +void ia64_fpstate_drop __P((struct proc *p)); +void ia64_fpstate_switch __P((struct proc *p)); +void init_prom_interface __P((struct rpb*)); +void interrupt + __P((unsigned long, unsigned long, unsigned long, struct trapframe *)); +void machine_check + __P((unsigned long, struct trapframe *, unsigned long, unsigned long)); +u_int64_t hwrpb_checksum __P((void)); +void hwrpb_restart_setup __P((void)); +void regdump __P((struct trapframe *)); +void regtoframe __P((struct reg *, struct trapframe *)); +int savectx __P((struct pcb *)); +void restorectx __P((struct pcb *)); +void set_iointr __P((void (*)(void *, unsigned long))); +void switch_exit __P((struct proc *)); /* MAGIC */ +void switch_trampoline __P((void)); /* MAGIC */ +void syscall __P((u_int64_t, struct trapframe *)); +void trap __P((int vector, struct trapframe *framep)); + +#endif /* _KERNEL */ + +#endif /* _MACHINE_CPU_H_ */ diff --git a/sys/ia64/include/cpufunc.h b/sys/ia64/include/cpufunc.h new file mode 100644 index 0000000..3128f70 --- /dev/null +++ b/sys/ia64/include/cpufunc.h @@ -0,0 +1,197 @@ +/*- + * 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_ + +#ifdef _KERNEL + +#include <sys/types.h> + +#ifdef __GNUC__ + +static __inline void +breakpoint(void) +{ + __asm __volatile("break 0x80100"); /* XXX use linux value */ +} + +#endif + +static __inline u_int8_t +inb(u_int port) +{ + return 0; /* TODO: implement this */ +} + +static __inline u_int16_t +inw(u_int port) +{ + return 0; /* TODO: implement this */ +} + +static __inline u_int32_t +inl(u_int port) +{ + return 0; /* TODO: implement this */ +} + +static __inline void +insb(u_int port, void *addr, size_t count) +{ + u_int8_t *p = addr; + while (count--) + *p++ = inb(port); +} + +static __inline void +insw(u_int port, void *addr, size_t count) +{ + u_int16_t *p = addr; + while (count--) + *p++ = inw(port); +} + +static __inline void +insl(u_int port, void *addr, size_t count) +{ + u_int32_t *p = addr; + while (count--) + *p++ = inl(port); +} + +static __inline void +outb(u_int port, u_int8_t data) +{ + return; /* TODO: implement this */ +} + +static __inline void +outw(u_int port, u_int16_t data) +{ + return; /* TODO: implement this */ +} + +static __inline void +outl(u_int port, u_int32_t data) +{ + return; /* TODO: implement this */ +} + +static __inline void +outsb(u_int port, const void *addr, size_t count) +{ + const u_int8_t *p = addr; + while (count--) + outb(port, *p++); +} + +static __inline void +outsw(u_int port, const void *addr, size_t count) +{ + const u_int16_t *p = addr; + while (count--) + outw(port, *p++); +} + +static __inline void +outsl(u_int port, const void *addr, size_t count) +{ + const u_int32_t *p = addr; + while (count--) + outl(port, *p++); +} + +static __inline u_int8_t +readb(u_int addr) +{ + return 0; /* TODO: implement this */ +} + +static __inline u_int16_t +readw(u_int addr) +{ + return 0; /* TODO: implement this */ +} + +static __inline u_int32_t +readl(u_int addr) +{ + return 0; /* TODO: implement this */ +} + +static __inline void +writeb(u_int addr, u_int8_t data) +{ + return; /* TODO: implement this */ +} + +static __inline void +writew(u_int addr, u_int16_t data) +{ + return; /* TODO: implement this */ +} + +static __inline void +writel(u_int addr, u_int32_t data) +{ + return; /* TODO: implement this */ +} + +/* + * Bogus interrupt manipulation + */ +static __inline void +disable_intr(void) +{ + __asm __volatile ("rsm psr.i;;"); +} + +static __inline void +enable_intr(void) +{ + __asm __volatile (";; ssm psr.i;; srlz.d"); +} + +static __inline u_int +save_intr(void) +{ + u_int psr; + __asm __volatile ("mov %0=psr;;" : "=r" (psr)); + return psr; +} + +static __inline void +restore_intr(u_int psr) +{ + __asm __volatile ("mov psr.l=%0;; srlz.d" :: "r" (psr)); +} + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_CPUFUNC_H_ */ diff --git a/sys/ia64/include/db_machdep.h b/sys/ia64/include/db_machdep.h new file mode 100644 index 0000000..1517a54 --- /dev/null +++ b/sys/ia64/include/db_machdep.h @@ -0,0 +1,91 @@ +/* $FreeBSD$ */ +/* $NetBSD: db_machdep.h,v 1.6 1997/09/06 02:02:25 thorpej Exp $ */ + +/* + * Copyright (c) 1995 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. + */ + +#ifndef _ALPHA_DB_MACHDEP_H_ +#define _ALPHA_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include <sys/param.h> +#include <vm/vm.h> +#include <machine/frame.h> + +#define DB_NO_AOUT + +typedef vm_offset_t db_addr_t; /* address - unsigned */ +typedef long db_expr_t; /* expression - signed */ + +typedef struct trapframe db_regs_t; +db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((db_addr_t)(regs)->tf_regs[FRAME_PC]) + +#define BKPT_INST 0x00000080 /* breakpoint instruction */ +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define FIXUP_PC_AFTER_BREAK \ + (ddb_regs.tf_regs[FRAME_PC] -= BKPT_SIZE); + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == ALPHA_KENTRY_IF && \ + (code) == ALPHA_IF_CODE_BPT) +#define IS_WATCHPOINT_TRAP(type, code) 0 + +/* + * Functions needed for software single-stepping. + */ + +/* No delay slots on Alpha. */ +#define next_instr_address(v, b) ((db_addr_t) ((b) ? (v) : ((v) + 4))) + +u_long db_register_value __P((db_regs_t *, int)); +int kdb_trap __P((unsigned long, unsigned long, unsigned long, + unsigned long, struct trapframe *)); + +/* + * Pretty arbitrary + */ +#define DB_SMALL_VALUE_MAX 0x7fffffff +#define DB_SMALL_VALUE_MIN (-0x400001) + +/* + * We define some of our own commands. + */ +#define DB_MACHINE_COMMANDS + +/* + * We use Elf64 symbols in DDB. + */ +#define DB_ELFSIZE 64 + +#endif /* _ALPHA_DB_MACHDEP_H_ */ diff --git a/sys/ia64/include/efi.h b/sys/ia64/include/efi.h new file mode 100644 index 0000000..077fe89 --- /dev/null +++ b/sys/ia64/include/efi.h @@ -0,0 +1,71 @@ +/*- + * 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$ + */ + +#ifndef _MACHINE_EFI_H_ +#define _MACHINE_EFI_H_ + +/* + * Memory types. + */ +#define EFI_RESERVED_MEMORY_TYPE 0 +#define EFI_LOADER_CODE 1 +#define EFI_LOADER_DATA 2 +#define EFI_BOOT_SERVICES_CODE 3 +#define EFI_BOOT_SERVICES_DATA 4 +#define EFI_RUNTIME_SERVICES_CODE 5 +#define EFI_RUNTIME_SERVICES_DATA 6 +#define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNUSABLE_MEMORY 8 +#define EFI_ACPI_RECLAIM_MEMORY 9 +#define EFI_ACPI_MEMORY_NVS 10 +#define EFI_MEMORY_MAPPED_IO 11 +#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 +#define EFI_PAL_CODE 13 + +struct efi_memory_descriptor { + u_int32_t emd_type; + vm_offset_t emd_physical_start; + vm_offset_t emd_virtul_start; + u_int64_t emd_number_of_pages; + u_int64_t emd_attribute; +}; + +/* + * Values for emd_attribute. + */ +#define EFI_MEMORY_UC 0x0000000000000001 +#define EFI_MEMORY_WC 0x0000000000000002 +#define EFI_MEMORY_WT 0x0000000000000004 +#define EFI_MEMORY_WB 0x0000000000000008 +#define EFI_MEMORY_UCE 0x0000000000000010 +#define EFI_MEMORY_WP 0x0000000000001000 +#define EFI_MEMORY_RP 0x0000000000002000 +#define EFI_MEMORY_XP 0x0000000000004000 +#define EFI_MEMORY_RUNTIME 0x8000000000000000 + +#endif /* _MACHINE_EFI_H_ */ diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h new file mode 100644 index 0000000..3ed5220 --- /dev/null +++ b/sys/ia64/include/elf.h @@ -0,0 +1,203 @@ +/*- + * 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 + +/* + * ELF definitions for the IA-64 architecture. + */ + +#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */ + +#define __ELF_WORD_SIZE 64 /* Used by <sys/elf_generic.h> */ +#include <sys/elf_generic.h> + +#define ELF_ARCH EM_IA_64 + +#define ELF_MACHINE_OK(x) ((x) == EM_IA_64) + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The i386 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; +} Elf64_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 i386). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ + +/* + * The following non-standard values are used for passing information + * from John Polstra's testbed program to the dynamic linker. These + * are expected to go away soon. + * + * Unfortunately, these overlap the Linux non-standard values, so they + * must not be used in the same context. + */ +#define AT_BRK 10 /* Starting point for sbrk and brk. */ +#define AT_DEBUG 11 /* Debugging level. */ + +/* + * The following non-standard values are used in Linux ELF binaries. + */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ + +#define AT_COUNT 15 /* Count of defined aux entry types. */ + +/* + * Values for e_flags. + */ +#define EF_IA_64_MASKOS 0x00ff000f +#define EF_IA_64_ABI64 0x00000010 +#define EF_IA_64_REDUCEDFP 0x00000020 +#define EF_IA_64_CONS_GP 0x00000040 +#define EF_IA_64_NOFUNCDESC_CONS_GP 0x00000080 +#define EF_IA_64_ABSOLUTE 0x00000100 +#define EF_IA_64_ARCH 0xff000000 + +/* + * Section types. + */ +#define SHT_IA_64_EXT 0x70000000 +#define SHT_IA_64_UNWIND 0x70000001 +#define SHT_IA_64_LOPSREG 0x78000000 +#define SHT_IA_64_HIPSREG 0x7fffffff + +/* + * Section attribute flags. + */ +#define SHF_IA_64_SHORT 0x10000000 +#define SHF_IA_64_NORECOV 0x20000000 + +/* + * Relocation types. + */ + +/* Name Value Field Calculation */ +#define R_IA64_NONE 0 /* None */ +#define R_IA64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA64_SUB 0x85 /* immediate64 A - S */ +#define R_IA64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA64_LDXMOV 0x87 /* immediate22 special */ + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_IA_64 +#define ELF_TARG_VER 1 + +#ifdef _KERNEL + +/* + * On the ia64 we load the dynamic linker where a userland call + * to mmap(0, ...) would put it. The rationale behind this + * calculation is that it leaves room for the heap to grow to + * its maximum allowed size. + */ +#define ELF_RTLD_ADDR(vmspace) \ + (round_page((vm_offset_t)(vmspace)->vm_daddr + MAXDSIZ)) + +#endif /* _KERNEL */ +#endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/ia64/include/endian.h b/sys/ia64/include/endian.h new file mode 100644 index 0000000..67e4540 --- /dev/null +++ b/sys/ia64/include/endian.h @@ -0,0 +1,97 @@ +/* $FreeBSD$ */ +/* From: NetBSD: endian.h,v 1.5 1997/10/09 15:42:19 bouyer Exp */ + +/* + * 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. + * 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. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _ENDIAN_H_ +#define _ENDIAN_H_ + +/* + * Define the order of 32-bit words in 64-bit words. + */ +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 + +#ifndef _POSIX_SOURCE +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#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 LITTLE_ENDIAN + +#include <sys/cdefs.h> +#include <sys/types.h> + +typedef u_int32_t in_addr_t; +typedef u_int16_t in_port_t; + +__BEGIN_DECLS +in_addr_t htonl __P((in_addr_t)); +in_port_t htons __P((in_port_t)); +in_addr_t ntohl __P((in_addr_t)); +in_port_t ntohs __P((in_port_t)); +u_int16_t bswap16 __P((u_int16_t)); +u_int32_t bswap32 __P((u_int32_t)); +u_int64_t bswap64 __P((u_int64_t)); +__END_DECLS + +/* + * Macros for network/external number representation conversion. + */ +#if BYTE_ORDER == BIG_ENDIAN && !defined(lint) +#define ntohl(x) (x) +#define ntohs(x) (x) +#define htonl(x) (x) +#define htons(x) (x) + +#define NTOHL(x) (x) +#define NTOHS(x) (x) +#define HTONL(x) (x) +#define HTONS(x) (x) + +#else + +#define NTOHL(x) (x) = ntohl((in_addr_t)x) +#define NTOHS(x) (x) = ntohs((in_port_t)x) +#define HTONL(x) (x) = htonl((in_addr_t)x) +#define HTONS(x) (x) = htons((in_port_t)x) +#endif +#endif /* !_POSIX_SOURCE */ +#endif /* !_ENDIAN_H_ */ diff --git a/sys/ia64/include/exec.h b/sys/ia64/include/exec.h new file mode 100644 index 0000000..52baf9e --- /dev/null +++ b/sys/ia64/include/exec.h @@ -0,0 +1,35 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. 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$ + */ + +#define __LDPGSZ 4096 diff --git a/sys/ia64/include/float.h b/sys/ia64/include/float.h new file mode 100644 index 0000000..0420ffb --- /dev/null +++ b/sys/ia64/include/float.h @@ -0,0 +1,79 @@ +/* $FreeBSD$ */ +/* From: NetBSD: float.h,v 1.6 1997/07/17 21:36:03 thorpej Exp */ + +/* + * Copyright (c) 1989, 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. + */ + +#ifndef _MACHINE_FLOAT_H_ +#define _MACHINE_FLOAT_H_ + +#include <sys/cdefs.h> + +__BEGIN_DECLS +int __flt_rounds __P((void)); +__END_DECLS + +#define FLT_RADIX 2 /* b */ +#define FLT_ROUNDS __flt_rounds() + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP -125 /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP -1021 +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP -307 +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON DBL_EPSILON +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN DBL_MIN +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX DBL_MAX +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#endif /* _MACHINE_FLOAT_H_ */ diff --git a/sys/ia64/include/floatingpoint.h b/sys/ia64/include/floatingpoint.h new file mode 100644 index 0000000..e2faa5e --- /dev/null +++ b/sys/ia64/include/floatingpoint.h @@ -0,0 +1,35 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. 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$ + */ + +#include <machine/ieeefp.h> diff --git a/sys/ia64/include/fpu.h b/sys/ia64/include/fpu.h new file mode 100644 index 0000000..f9d426c --- /dev/null +++ b/sys/ia64/include/fpu.h @@ -0,0 +1,81 @@ +/*- + * 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_FPU_H_ +#define _MACHINE_FPU_H_ + +/* + * Floating point status register bits. + */ + +#define IA64_FPSR_TRAP_VD 0x0000000000000001L +#define IA64_FPSR_TRAP_DD 0x0000000000000002L +#define IA64_FPSR_TRAP_ZD 0x0000000000000004L +#define IA64_FPSR_TRAP_OD 0x0000000000000008L +#define IA64_FPSR_TRAP_UD 0x0000000000000010L +#define IA64_FPSR_TRAP_ID 0x0000000000000020L +#define IA64_FPSR_SF(i,v) ((v) << ((i)*13+6)) + +#define IA64_SF_FTZ 0x0001L +#define IA64_SF_WRE 0x0002L +#define IA64_SF_PC 0x000cL +#define IA64_SF_PC_0 0x0000L +#define IA64_SF_PC_1 0x0004L +#define IA64_SF_PC_2 0x0008L +#define IA64_SF_PC_3 0x000cL +#define IA64_SF_RC 0x0030L +#define IA64_SF_RC_NEAREST 0x0000L +#define IA64_SF_RC_NEGINF 0x0010L +#define IA64_SF_RC_POSINF 0x0020L +#define IA64_SF_RC_TRUNC 0x0030L +#define IA64_SF_TD 0x0040L +#define IA64_SF_V 0x0080L +#define IA64_SF_D 0x0100L +#define IA64_SF_Z 0x0200L +#define IA64_SF_O 0x0400L +#define IA64_SF_U 0x0800L +#define IA64_SF_I 0x1000L + +#define IA64_SF_DEFAULT (IA64_SF_PC_3 | IA64_SF_RC_NEAREST) + +#define IA64_FPSR_DEFAULT (IA64_FPSR_TRAP_VD \ + | IA64_FPSR_TRAP_DD \ + | IA64_FPSR_TRAP_ZD \ + | IA64_FPSR_TRAP_OD \ + | IA64_FPSR_TRAP_UD \ + | IA64_FPSR_TRAP_ID \ + | IA64_FPSR_SF(0, IA64_SF_DEFAULT) \ + | IA64_FPSR_SF(1, (IA64_SF_DEFAULT \ + | IA64_SF_TD \ + | IA64_SF_WRE)) \ + | IA64_FPSR_SF(2, (IA64_SF_DEFAULT \ + | IA64_SF_TD)) \ + | IA64_FPSR_SF(3, (IA64_SF_DEFAULT \ + | IA64_SF_TD))) + +#endif /* ! _MACHINE_FPU_H_ */ diff --git a/sys/ia64/include/frame.h b/sys/ia64/include/frame.h new file mode 100644 index 0000000..2304770 --- /dev/null +++ b/sys/ia64/include/frame.h @@ -0,0 +1,114 @@ +/*- + * 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$ + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#include <machine/reg.h> + +/* + * Software trap, exception, and syscall frame. + * + * This is loosely based on the Linux pt_regs structure. When I + * understand things better, I might change it. + */ +struct trapframe { + u_int64_t tf_cr_iip; + u_int64_t tf_cr_ipsr; + u_int64_t tf_cr_isr; + u_int64_t tf_cr_ifa; + u_int64_t tf_pr; + u_int64_t tf_ar_rsc; + u_int64_t tf_ar_pfs; + u_int64_t tf_cr_ifs; + u_int64_t tf_ar_bspstore; + u_int64_t tf_ar_rnat; + u_int64_t tf_ar_bsp; + u_int64_t tf_ar_unat; + u_int64_t tf_ar_ccv; + u_int64_t tf_ar_fpsr; + + u_int64_t tf_b[8]; + + u_int64_t tf_r[31]; /* don't need to save r0 */ +#define FRAME_R1 0 +#define FRAME_GP 0 +#define FRAME_R2 1 +#define FRAME_R3 2 +#define FRAME_R4 3 +#define FRAME_R5 4 +#define FRAME_R6 5 +#define FRAME_R7 6 +#define FRAME_R8 7 +#define FRAME_R9 8 +#define FRAME_R10 9 +#define FRAME_R11 10 +#define FRAME_R12 11 +#define FRAME_SP 11 +#define FRAME_R13 12 +#define FRAME_TP 12 +#define FRAME_R14 13 +#define FRAME_R15 14 +#define FRAME_R16 15 +#define FRAME_R17 16 +#define FRAME_R18 17 +#define FRAME_R19 18 +#define FRAME_R20 19 +#define FRAME_R21 20 +#define FRAME_R22 21 +#define FRAME_R23 22 +#define FRAME_R24 23 +#define FRAME_R25 24 +#define FRAME_R26 25 +#define FRAME_R27 26 +#define FRAME_R28 27 +#define FRAME_R29 28 +#define FRAME_R30 29 +#define FRAME_R31 30 + + u_int64_t tf_pad1; + + /* + * We rely on the compiler to save/restore f2-f5 and + * f16-f31. We also tell the compiler to avoid f32-f127 + * completely so we don't worry about them at all. + */ + struct ia64_fpreg tf_f[10]; +#define FRAME_F6 0 +#define FRAME_F7 1 +#define FRAME_F8 2 +#define FRAME_F9 3 +#define FRAME_F10 3 +#define FRAME_F11 3 +#define FRAME_F12 3 +#define FRAME_F13 3 +#define FRAME_F14 3 +#define FRAME_F15 3 +}; + +#endif /* _MACHINE_FRAME_H_ */ diff --git a/sys/ia64/include/globaldata.h b/sys/ia64/include/globaldata.h new file mode 100644 index 0000000..87c9fe5 --- /dev/null +++ b/sys/ia64/include/globaldata.h @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1999 Luoqi Chen <luoqi@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_GLOBALDATA_H_ +#define _MACHINE_GLOBALDATA_H_ + +#ifdef _KERNEL + +#include <sys/queue.h> + +/* + * This structure maps out the global data that needs to be kept on a + * per-cpu basis. genassym uses this to generate offsets for the assembler + * code, which also provides external symbols so that C can get at them as + * though they were really globals. This structure is pointed to by + * the per-cpu system value (see alpha_pal_rdval() and alpha_pal_wrval()). + * Inside the kernel, the globally reserved register t7 is used to + * point at the globaldata structure. + */ +struct globaldata { + struct proc *gd_curproc; /* current process */ + struct proc *gd_idleproc; /* idle process */ + struct proc *gd_fpcurproc; /* fp state owner */ + struct pcb *gd_curpcb; /* current pcb */ + struct timeval gd_switchtime; + int gd_switchticks; + u_int gd_cpuno; /* this cpu number */ + u_int gd_other_cpus; /* all other cpus */ + int gd_inside_intr; + u_int64_t gd_idlepcbphys; /* pa of gd_idlepcb */ + u_int64_t gd_pending_ipis; /* pending IPI events */ + u_int32_t gd_next_asn; /* next ASN to allocate */ + u_int32_t gd_current_asngen; /* ASN rollover check */ + u_int32_t gd_intr_nesting_level; /* interrupt recursion */ + + u_int gd_astpending; + SLIST_ENTRY(globaldata) gd_allcpu; +#ifdef KTR_PERCPU + volatile int gd_ktr_idx; /* Index into trace table */ + char *gd_ktr_buf; + char gd_ktr_buf_data[0]; +#endif +}; + +SLIST_HEAD(cpuhead, globaldata); +extern struct cpuhead cpuhead; + +void globaldata_init(struct globaldata *pcpu, int cpuno, size_t sz); +struct globaldata *globaldata_find(int cpuno); + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_GLOBALDATA_H_ */ diff --git a/sys/ia64/include/globals.h b/sys/ia64/include/globals.h new file mode 100644 index 0000000..4046bff --- /dev/null +++ b/sys/ia64/include/globals.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 1999 Luoqi Chen <luoqi@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_GLOBALS_H_ +#define _MACHINE_GLOBALS_H_ + +#ifdef _KERNEL + +register struct globaldata *globalp __asm__("r13"); + +#if 1 +#define GLOBALP globalp +#else +#define GLOBALP ((struct globaldata *) alpha_pal_rdval()) +#endif + +#define PCPU_GET(name) (GLOBALP->gd_##name) +#define PCPU_SET(name,value) (GLOBALP->gd_##name = (value)) + +/* + * The following set of macros works for UP kernel as well, but for maximum + * performance we allow the global variables to be accessed directly. On the + * other hand, kernel modules should always use these macros to maintain + * portability between UP and SMP kernels. + */ +#define CURPROC PCPU_GET(curproc) +#define curproc PCPU_GET(curproc) +#define idleproc PCPU_GET(idleproc) +#define curpcb PCPU_GET(curpcb) +#define fpcurproc PCPU_GET(fpcurproc) +#define switchtime PCPU_GET(switchtime) +#define switchticks PCPU_GET(switchticks) +#define cpuid PCPU_GET(cpuno) +#define prevproc PCPU_GET(curproc) /* XXX - until ithreads */ + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_GLOBALS_H_ */ diff --git a/sys/ia64/include/ia64_cpu.h b/sys/ia64/include/ia64_cpu.h new file mode 100644 index 0000000..ca205c2 --- /dev/null +++ b/sys/ia64/include/ia64_cpu.h @@ -0,0 +1,203 @@ +/*- + * 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$ + */ + +#ifndef _MACHINE_IA64_CPU_H_ +#define _MACHINE_IA64_CPU_H_ + +/* + * Definition of PSR and IPSR bits. + */ +#define IA64_PSR_BE 0x0000000000000002 +#define IA64_PSR_UP 0x0000000000000004 +#define IA64_PSR_AC 0x0000000000000008 +#define IA64_PSR_MFL 0x0000000000000010 +#define IA64_PSR_MFH 0x0000000000000020 +#define IA64_PSR_IC 0x0000000000002000 +#define IA64_PSR_I 0x0000000000004000 +#define IA64_PSR_PK 0x0000000000008000 +#define IA64_PSR_DT 0x0000000000020000 +#define IA64_PSR_DFL 0x0000000000040000 +#define IA64_PSR_DFH 0x0000000000080000 +#define IA64_PSR_SP 0x0000000000100000 +#define IA64_PSR_PP 0x0000000000200000 +#define IA64_PSR_DI 0x0000000000400000 +#define IA64_PSR_SI 0x0000000000800000 +#define IA64_PSR_DB 0x0000000001000000 +#define IA64_PSR_LP 0x0000000002000000 +#define IA64_PSR_TB 0x0000000004000000 +#define IA64_PSR_RT 0x0000000008000000 +#define IA64_PSR_CPL 0x0000000300000000 +#define IA64_PSR_CPL_KERN 0x0000000000000000 +#define IA64_PSR_CPL_1 0x0000000100000000 +#define IA64_PSR_CPL_2 0x0000000200000000 +#define IA64_PSR_CPL_USER 0x0000000300000000 +#define IA64_PSR_IS 0x0000000400000000 +#define IA64_PSR_MC 0x0000000800000000 +#define IA64_PSR_IT 0x0000001000000000 +#define IA64_PSR_ID 0x0000002000000000 +#define IA64_PSR_DA 0x0000004000000000 +#define IA64_PSR_DD 0x0000008000000000 +#define IA64_PSR_SS 0x0000010000000000 +#define IA64_PSR_RI 0x0000060000000000 +#define IA64_PSR_RI_0 0x0000000000000000 +#define IA64_PSR_RI_1 0x0000020000000000 +#define IA64_PSR_RI_2 0x0000040000000000 +#define IA64_PSR_ED 0x0000080000000000 +#define IA64_PSR_BN 0x0000100000000000 +#define IA64_PSR_IA 0x0000200000000000 + +/* + * Definition of ISR bits. + */ +#define IA64_ISR_CODE 0x000000000000ffff +#define IA64_ISR_VECTOR 0x0000000000ff0000 +#define IA64_ISR_X 0x0000000100000000 +#define IA64_ISR_W 0x0000000200000000 +#define IA64_ISR_R 0x0000000400000000 +#define IA64_ISR_NA 0x0000000800000000 +#define IA64_ISR_SP 0x0000001000000000 +#define IA64_ISR_RS 0x0000002000000000 +#define IA64_ISR_IR 0x0000004000000000 +#define IA64_ISR_NI 0x0000008000000000 +#define IA64_ISR_SO 0x0000010000000000 +#define IA64_ISR_EI 0x0000060000000000 +#define IA64_ISR_EI_0 0x0000000000000000 +#define IA64_ISR_EI_1 0x0000020000000000 +#define IA64_ISR_EI_2 0x0000040000000000 +#define IA64_ISR_ED 0x0000080000000000 + +/* + * Vector numbers for various ia64 interrupts. + */ +#define IA64_VEC_VHPT 0 +#define IA64_VEC_ITLB 1 +#define IA64_VEC_DTLB 2 +#define IA64_VEC_ALT_ITLB 3 +#define IA64_VEC_ALT_DTLB 4 +#define IA64_VEC_NESTED_DTLB 5 +#define IA64_VEC_IKEY_MISS 6 +#define IA64_VEC_DKEY_MISS 7 +#define IA64_VEC_DIRTY_BIT 8 +#define IA64_VEC_INST_ACCESS 9 +#define IA64_VEC_DATA_ACCESS 10 +#define IA64_VEC_BREAK 11 +#define IA64_VEC_EXT_INTR 12 +#define IA64_VEC_PAGE_NOT_PRESENT 20 +#define IA64_VEC_KEY_PERMISSION 21 +#define IA64_VEC_INST_ACCESS_RIGHTS 22 +#define IA64_VEC_DATA_ACCESS_RIGHTS 23 +#define IA64_VEC_GENERAL_EXCEPTION 24 +#define IA64_VEC_DISABLED_FP 25 +#define IA64_VEC_NAT_CONSUMPTION 26 +#define IA64_VEC_SPECULATION 27 +#define IA64_VEC_DEBUG 29 +#define IA64_VEC_UNALIGNED_REFERENCE 30 +#define IA64_VEC_UNSUPP_DATA_REFERENCE 31 +#define IA64_VEC_FLOATING_POINT_FAULT 32 +#define IA64_VEC_FLOATING_POINT_TRAP 33 +#define IA64_VEC_LOWER_PRIVILEGE_TRANSFER 34 +#define IA64_VEC_TAKEN_BRANCH_TRAP 35 +#define IA64_VEC_SINGLE_STEP_TRAP 36 +#define IA64_VEC_IA32_EXCEPTION 45 +#define IA64_VEC_IA32_INTERCEPT 46 +#define IA64_VEC_IA32_INTERRUPT 47 + +/* + * Manipulating region bits of an address. + */ +#define IA64_RR_BASE(n) (((u_int64_t) (n)) << 61) +#define IA64_RR_MASK(x) ((x) & ((1L << 61) - 1)) + +#define IA64_PHYS_TO_RR6(x) ((x) | IA64_RR_BASE(6)) +#define IA64_PHYS_TO_RR7(x) ((x) | IA64_RR_BASE(7)) + +/* + * Various special ia64 instructions. + */ + +/* + * Memory Fence. + */ +static __inline void +ia64_mf(void) +{ + __asm __volatile("mf"); +} + +/* + * Calculate address in VHPT for va. + */ +static __inline u_int64_t +ia64_thash(u_int64_t va) +{ + u_int64_t result; + __asm __volatile("thash %0=%1" : "=r" (result) : "r" (va)); + return result; +} + +/* + * Calculate VHPT tag for va. + */ +static __inline u_int64_t +ia64_ttag(u_int64_t va) +{ + u_int64_t result; + __asm __volatile("ttag %0=%1" : "=r" (result) : "r" (va)); + return result; +} + +/* + * Convert virtual address to physical. + */ +static __inline u_int64_t +ia64_tpa(u_int64_t va) +{ + u_int64_t result; + __asm __volatile("tpa %0=%1" : "=r" (result) : "r" (va)); + return result; +} + +/* + * Read the value of ar.itc. + */ +static __inline u_int64_t +ia64_read_itc(void) +{ + u_int64_t result; + __asm __volatile("mov %0=ar.itc" : "=r" (result)); + return result; +} + +static __inline void +ia64_set_rr(u_int64_t rrbase, u_int64_t v) +{ + __asm __volatile("mov rr[%0]=%1" :: "r"(rrbase), "r"(v) : "memory"); +} + +#endif /* _MACHINE_IA64_CPU_H_ */ + diff --git a/sys/ia64/include/ieee.h b/sys/ia64/include/ieee.h new file mode 100644 index 0000000..654d6ee --- /dev/null +++ b/sys/ia64/include/ieee.h @@ -0,0 +1,124 @@ +/* $FreeBSD$ */ +/* From: NetBSD: ieee.h,v 1.2 1997/04/06 08:47:27 cgd Exp */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + * + * from: Header: ieee.h,v 1.7 92/11/26 02:04:37 torek Exp + */ + +/* + * 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 + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +/* + * 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 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 diff --git a/sys/ia64/include/ieeefp.h b/sys/ia64/include/ieeefp.h new file mode 100644 index 0000000..d673507 --- /dev/null +++ b/sys/ia64/include/ieeefp.h @@ -0,0 +1,29 @@ +/* $FreeBSD$ */ +/* From: NetBSD: ieeefp.h,v 1.2 1997/04/06 08:47:28 cgd Exp */ + +/* + * Written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _ALPHA_IEEEFP_H_ +#define _ALPHA_IEEEFP_H_ + +typedef int fp_except_t; +#define FP_X_INV (1LL << 1) /* invalid operation exception */ +#define FP_X_DZ (1LL << 2) /* divide-by-zero exception */ +#define FP_X_OFL (1LL << 3) /* overflow exception */ +#define FP_X_UFL (1LL << 4) /* underflow exception */ +#define FP_X_IMP (1LL << 5) /* imprecise(inexact) exception */ +#if 0 +#define FP_X_IOV (1LL << 6) /* integer overflow XXX? */ +#endif + +typedef enum { + FP_RZ=0, /* round to zero (truncate) */ + FP_RM=1, /* round toward negative infinity */ + FP_RN=2, /* round to nearest representable number */ + FP_RP=3 /* round toward positive infinity */ +} fp_rnd_t; + +#endif /* _ALPHA_IEEEFP_H_ */ diff --git a/sys/ia64/include/in_cksum.h b/sys/ia64/include/in_cksum.h new file mode 100644 index 0000000..7a98720 --- /dev/null +++ b/sys/ia64/include/in_cksum.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * 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 __GNUC__ + +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/ia64/include/intr.h b/sys/ia64/include/intr.h new file mode 100644 index 0000000..4f00388 --- /dev/null +++ b/sys/ia64/include/intr.h @@ -0,0 +1,37 @@ +/*- + * 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_INTR_H_ +#define _MACHINE_INTR_H_ + +int alpha_setup_intr(int vector, driver_intr_t *intr, void *arg, + void **cookiep, volatile long *cntp); +int alpha_teardown_intr(void *cookie); +void alpha_dispatch_intr(void *frame, unsigned long vector); + +#endif /* !_MACHINE_INTR_H_ */ diff --git a/sys/ia64/include/intrcnt.h b/sys/ia64/include/intrcnt.h new file mode 100644 index 0000000..440f819 --- /dev/null +++ b/sys/ia64/include/intrcnt.h @@ -0,0 +1,79 @@ +/* $FreeBSD$ */ +/* $NetBSD: intrcnt.h,v 1.17 1998/11/19 01:48:04 ross Exp $ */ + +/* + * Copyright (c) 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. + */ + +#define INTRCNT_CLOCK 0 +#define INTRCNT_ISA_IRQ (INTRCNT_CLOCK + 1) +#define INTRCNT_ISA_IRQ_LEN 16 +#define INTRCNT_OTHER_BASE (INTRCNT_ISA_IRQ + INTRCNT_ISA_IRQ_LEN) +#define INTRCNT_OTHER_LEN 48 +#define INTRCNT_COUNT (INTRCNT_OTHER_BASE + INTRCNT_OTHER_LEN) + +#define INTRCNT_A12_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_DEC_1000A_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_DEC_1000_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_DEC_2100_A500_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_DEC_550_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_EB164_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_EB64PLUS_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_EB66_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_IOASIC INTRCNT_OTHER_BASE +#define INTRCNT_KN15 INTRCNT_OTHER_BASE +#define INTRCNT_KN16 INTRCNT_OTHER_BASE +#define INTRCNT_KN20AA_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_KN300_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_KN8AE_IRQ INTRCNT_OTHER_BASE +#define INTRCNT_TCDS INTRCNT_OTHER_BASE + +#define INTRCNT_A12_IRQ_LEN 10 +#define INTRCNT_DEC_1000A_IRQ_LEN 32 +#define INTRCNT_DEC_1000_IRQ_LEN 16 +#define INTRCNT_DEC_2100_A500_IRQ_LEN 16 +#define INTRCNT_DEC_550_IRQ_LEN 48 +#define INTRCNT_EB164_IRQ_LEN 24 +#define INTRCNT_EB64PLUS_IRQ_LEN 32 +#define INTRCNT_EB66_IRQ_LEN 32 +#define INTRCNT_IOASIC_LEN 4 +#define INTRCNT_ISA_IRQ_LEN 16 +#define INTRCNT_KN15_LEN 9 +#define INTRCNT_KN16_LEN 5 +#define INTRCNT_KN20AA_IRQ_LEN 32 +#define INTRCNT_KN300_LEN 19 +#define INTRCNT_KN8AE_IRQ_LEN 2 +#define INTRCNT_TCDS_LEN 2 + +# define INTRCNT_KN300_NCR810 INTRCNT_KN300_IRQ + 16 +# define INTRCNT_KN300_I2C_CTRL INTRCNT_KN300_IRQ + 17 +# define INTRCNT_KN300_I2C_BUS INTRCNT_KN300_IRQ + 18 + +#ifdef _KERNEL +#ifndef _LOCORE +extern volatile long intrcnt[]; +#endif +#endif diff --git a/sys/ia64/include/ioctl_bt848.h b/sys/ia64/include/ioctl_bt848.h new file mode 100644 index 0000000..4b6a8fb --- /dev/null +++ b/sys/ia64/include/ioctl_bt848.h @@ -0,0 +1,288 @@ +/* + * extensions to ioctl_meteor.h for the bt848 cards + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_IOCTL_BT848_H_ +#define _MACHINE_IOCTL_BT848_H_ + +/* + * frequency sets + */ +#define CHNLSET_NABCST 1 +#define CHNLSET_CABLEIRC 2 +#define CHNLSET_CABLEHRC 3 +#define CHNLSET_WEUROPE 4 +#define CHNLSET_JPNBCST 5 +#define CHNLSET_JPNCABLE 6 +#define CHNLSET_XUSSR 7 +#define CHNLSET_AUSTRALIA 8 +#define CHNLSET_FRANCE 9 +#define CHNLSET_MIN CHNLSET_NABCST +#define CHNLSET_MAX CHNLSET_FRANCE + + +/* + * constants for various tuner registers + */ +#define BT848_HUEMIN (-90) +#define BT848_HUEMAX 90 +#define BT848_HUECENTER 0 +#define BT848_HUERANGE 179.3 +#define BT848_HUEREGMIN (-128) +#define BT848_HUEREGMAX 127 +#define BT848_HUESTEPS 256 + +#define BT848_BRIGHTMIN (-50) +#define BT848_BRIGHTMAX 50 +#define BT848_BRIGHTCENTER 0 +#define BT848_BRIGHTRANGE 99.6 +#define BT848_BRIGHTREGMIN (-128) +#define BT848_BRIGHTREGMAX 127 +#define BT848_BRIGHTSTEPS 256 + +#define BT848_CONTRASTMIN 0 +#define BT848_CONTRASTMAX 237 +#define BT848_CONTRASTCENTER 100 +#define BT848_CONTRASTRANGE 236.57 +#define BT848_CONTRASTREGMIN 0 +#define BT848_CONTRASTREGMAX 511 +#define BT848_CONTRASTSTEPS 512 + +#define BT848_CHROMAMIN 0 +#define BT848_CHROMAMAX 284 +#define BT848_CHROMACENTER 100 +#define BT848_CHROMARANGE 283.89 +#define BT848_CHROMAREGMIN 0 +#define BT848_CHROMAREGMAX 511 +#define BT848_CHROMASTEPS 512 + +#define BT848_SATUMIN 0 +#define BT848_SATUMAX 202 +#define BT848_SATUCENTER 100 +#define BT848_SATURANGE 201.18 +#define BT848_SATUREGMIN 0 +#define BT848_SATUREGMAX 511 +#define BT848_SATUSTEPS 512 + +#define BT848_SATVMIN 0 +#define BT848_SATVMAX 284 +#define BT848_SATVCENTER 100 +#define BT848_SATVRANGE 283.89 +#define BT848_SATVREGMIN 0 +#define BT848_SATVREGMAX 511 +#define BT848_SATVSTEPS 512 + + +/* + * audio stuff + */ +#define AUDIO_TUNER 0x00 /* command for the audio routine */ +#define AUDIO_EXTERN 0x01 /* don't confuse them with bit */ +#define AUDIO_INTERN 0x02 /* settings */ +#define AUDIO_MUTE 0x80 +#define AUDIO_UNMUTE 0x81 + + +/* + * EEProm stuff + */ +struct eeProm { + short offset; + short count; + u_char bytes[ 256 ]; +}; + + +/* + * XXX: this is a hack, should be in ioctl_meteor.h + * here to avoid touching that file for now... + */ +#define TVTUNER_SETCHNL _IOW('x', 32, unsigned int) /* set channel */ +#define TVTUNER_GETCHNL _IOR('x', 32, unsigned int) /* get channel */ +#define TVTUNER_SETTYPE _IOW('x', 33, unsigned int) /* set tuner type */ +#define TVTUNER_GETTYPE _IOR('x', 33, unsigned int) /* get tuner type */ +#define TVTUNER_GETSTATUS _IOR('x', 34, unsigned int) /* get tuner status */ +#define TVTUNER_SETFREQ _IOW('x', 35, unsigned int) /* set frequency */ +#define TVTUNER_GETFREQ _IOR('x', 36, unsigned int) /* get frequency */ + + +#define BT848_SHUE _IOW('x', 37, int) /* set hue */ +#define BT848_GHUE _IOR('x', 37, int) /* get hue */ +#define BT848_SBRIG _IOW('x', 38, int) /* set brightness */ +#define BT848_GBRIG _IOR('x', 38, int) /* get brightness */ +#define BT848_SCSAT _IOW('x', 39, int) /* set chroma sat */ +#define BT848_GCSAT _IOR('x', 39, int) /* get UV saturation */ +#define BT848_SCONT _IOW('x', 40, int) /* set contrast */ +#define BT848_GCONT _IOR('x', 40, int) /* get contrast */ +#define BT848_SVSAT _IOW('x', 41, int) /* set chroma V sat */ +#define BT848_GVSAT _IOR('x', 41, int) /* get V saturation */ +#define BT848_SUSAT _IOW('x', 42, int) /* set chroma U sat */ +#define BT848_GUSAT _IOR('x', 42, int) /* get U saturation */ + +#define BT848_SCBARS _IOR('x', 43, int) /* set colorbar */ +#define BT848_CCBARS _IOR('x', 44, int) /* clear colorbar */ + + +#define BT848_SAUDIO _IOW('x', 46, int) /* set audio channel */ +#define BT848_GAUDIO _IOR('x', 47, int) /* get audio channel */ +#define BT848_SBTSC _IOW('x', 48, int) /* set audio channel */ + +#define BT848_GSTATUS _IOR('x', 49, unsigned int) /* reap status */ + +#define BT848_WEEPROM _IOWR('x', 50, struct eeProm) /* write to EEProm */ +#define BT848_REEPROM _IOWR('x', 51, struct eeProm) /* read from EEProm */ + +#define BT848_SIGNATURE _IOWR('x', 52, struct eeProm) /* read card sig */ + +#define TVTUNER_SETAFC _IOW('x', 53, int) /* turn AFC on/off */ +#define TVTUNER_GETAFC _IOR('x', 54, int) /* query AFC on/off */ +#define BT848_SLNOTCH _IOW('x', 55, int) /* set luma notch */ +#define BT848_GLNOTCH _IOR('x', 56, int) /* get luma notch */ + +/* Read/Write the BT848's I2C bus directly + * b7-b0: data (read/write) + * b15-b8: internal peripheral register (write) + * b23-b16: i2c addr (write) + * b31-b24: 1 = write, 0 = read + */ +#define BT848_I2CWR _IOWR('x', 57, u_long) /* i2c read-write */ + +/* Support for radio tuner */ +#define RADIO_SETMODE _IOW('x', 58, unsigned int) /* set radio modes */ +#define RADIO_GETMODE _IOR('x', 58, unsigned char) /* get radio modes */ +#define RADIO_AFC 0x01 /* These modes will probably not */ +#define RADIO_MONO 0x02 /* work on the FRxxxx. It does */ +#define RADIO_MUTE 0x08 /* work on the FMxxxx. */ +#define RADIO_SETFREQ _IOW('x', 59, unsigned int) /* set frequency */ +#define RADIO_GETFREQ _IOR('x', 59, unsigned int) /* set frequency */ + /* Argument is frequency*100MHz */ + +/* + * XXX: more bad magic, + * we need to fix the METEORGINPUT to return something public + * duplicate them here for now... + */ +#define METEOR_DEV0 0x00001000 +#define METEOR_DEV1 0x00002000 +#define METEOR_DEV2 0x00004000 +#define METEOR_DEV3 0x00008000 +#define METEOR_DEV_SVIDEO 0x00006000 +/* + * right now I don't know were to put these, but as they are suppose to be + * a part of a common video capture interface, these should be relocated to + * another place. Probably most of the METEOR_xxx defines need to be + * renamed and moved to a common header + */ + +typedef enum { METEOR_PIXTYPE_RGB, METEOR_PIXTYPE_YUV, + METEOR_PIXTYPE_YUV_PACKED, + METEOR_PIXTYPE_YUV_12 } METEOR_PIXTYPE; + + +struct meteor_pixfmt { + u_int index; /* Index in supported pixfmt list */ + METEOR_PIXTYPE type; /* What's the board gonna feed us */ + u_int Bpp; /* Bytes per pixel */ + u_long masks[3]; /* R,G,B or Y,U,V masks, respectively */ + unsigned swap_bytes :1; /* Bytes swapped within shorts */ + unsigned swap_shorts:1; /* Shorts swapped within longs */ +}; + + +struct bktr_clip { + int x_min; + int x_max; + int y_min; + int y_max; +}; + +#define BT848_MAX_CLIP_NODE 100 +struct _bktr_clip { + struct bktr_clip x[BT848_MAX_CLIP_NODE]; +}; + +/* + * I'm using METEOR_xxx just because that will be common to other interface + * and less of a surprise + */ +#define METEORSACTPIXFMT _IOW('x', 64, int ) +#define METEORGACTPIXFMT _IOR('x', 64, int ) +#define METEORGSUPPIXFMT _IOWR('x', 65, struct meteor_pixfmt) + +/* set clip list */ +#define BT848SCLIP _IOW('x', 66, struct _bktr_clip ) +#define BT848GCLIP _IOR('x', 66, struct _bktr_clip ) + + +/* set input format */ +#define BT848SFMT _IOW('x', 67, unsigned long ) +#define BT848GFMT _IOR('x', 67, unsigned long ) + +/* set clear-buffer-on-start */ +#define BT848SCBUF _IOW('x', 68, int) +#define BT848GCBUF _IOR('x', 68, int) + +/* set capture area */ +/* The capture area is the area of the video image which is grabbed */ +/* Usually the capture area is 640x480 (768x576 PAL) pixels */ +/* This area is then scaled to the dimensions the user requires */ +/* using the METEORGEO ioctl */ +/* However, the capture area could be 400x300 pixels from the top right */ +/* corner of the video image */ +struct bktr_capture_area { + int x_offset; + int y_offset; + int x_size; + int y_size; +}; +#define BT848_SCAPAREA _IOW('x', 69, struct bktr_capture_area) +#define BT848_GCAPAREA _IOR('x', 69, struct bktr_capture_area) + + +/* Get channel Set */ +#define BT848_MAX_CHNLSET_NAME_LEN 16 +struct bktr_chnlset { + short index; + short max_channel; + char name[BT848_MAX_CHNLSET_NAME_LEN]; +}; +#define TVTUNER_GETCHNLSET _IOWR('x', 70, struct bktr_chnlset) + + + +/* Infra Red Remote Control */ +struct bktr_remote { + unsigned char data[3]; +}; +#define REMOTE_GETKEY _IOR('x', 71, struct bktr_remote)/*read the remote */ + /*control receiver*/ + /*returns raw data*/ + + +/* + * Direct access to GPIO pins. You must add BKTR_GPIO_ACCESS to your kernel + * configuration file to use these + */ +#define BT848_GPIO_SET_EN _IOW('x', 72, int) /* set gpio_out_en */ +#define BT848_GPIO_GET_EN _IOR('x', 73, int) /* get gpio_out_en */ +#define BT848_GPIO_SET_DATA _IOW('x', 74, int) /* set gpio_data */ +#define BT848_GPIO_GET_DATA _IOR('x', 75, int) /* get gpio_data */ + + + +/* XXX - Copied from /sys/pci/brktree_reg.h */ +#define BT848_IFORM_FORMAT (0x7<<0) +# define BT848_IFORM_F_RSVD (0x7) +# define BT848_IFORM_F_SECAM (0x6) +# define BT848_IFORM_F_PALN (0x5) +# define BT848_IFORM_F_PALM (0x4) +# define BT848_IFORM_F_PALBDGHI (0x3) +# define BT848_IFORM_F_NTSCJ (0x2) +# define BT848_IFORM_F_NTSCM (0x1) +# define BT848_IFORM_F_AUTO (0x0) + + +#endif /* _MACHINE_IOCTL_BT848_H_ */ + diff --git a/sys/ia64/include/ioctl_fd.h b/sys/ia64/include/ioctl_fd.h new file mode 100644 index 0000000..dd6e9d0 --- /dev/null +++ b/sys/ia64/include/ioctl_fd.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden + * 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(S) ``AS IS'' AND ANY + * EXPRESS OR 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(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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$ + * from: ioctl_fd.h,v 1.11 + */ + +#ifndef _MACHINE_IOCTL_FD_H_ +#define _MACHINE_IOCTL_FD_H_ + +#ifndef _KERNEL +#include <sys/types.h> +#endif +#include <sys/ioccom.h> + +#define FD_FORMAT_VERSION 110 /* used to validate before formatting */ +#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */ + /* 2.88 MB drives */ + +struct fd_formb { + int format_version; /* == FD_FORMAT_VERSION */ + int cyl, head; + int transfer_rate; /* fdreg.h: FDC_???KBPS */ + + union { + struct fd_form_data { + /* + * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS + * it is hardware-dependent since it exactly + * matches the byte sequence to write to FDC + * during its `format track' operation + */ + u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */ + u_char nsecs; /* must be <= FD_MAX_NSEC */ + u_char gaplen; /* GAP 3 length; usually 84 */ + u_char fillbyte; /* usually 0xf6 */ + struct fd_idfield_data { + /* + * data to write into id fields; + * for obscure formats, they mustn't match + * the real values (but mostly do) + */ + u_char cylno; /* 0 thru 79 (or 39) */ + u_char headno; /* 0, or 1 */ + u_char secno; /* starting at 1! */ + u_char secsize; /* usually 2 */ + } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */ + } structured; + u_char raw[1]; /* to have continuous indexed access */ + } format_info; +}; + +/* make life easier */ +# define fd_formb_secshift format_info.structured.secshift +# define fd_formb_nsecs format_info.structured.nsecs +# define fd_formb_gaplen format_info.structured.gaplen +# define fd_formb_fillbyte format_info.structured.fillbyte +/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */ +# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno +# define fd_formb_headno(i) format_info.structured.idfields[i].headno +# define fd_formb_secno(i) format_info.structured.idfields[i].secno +# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize + +struct fd_type { + int sectrac; /* sectors per track */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int gap; /* gap len between sectors */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int steptrac; /* steps per cylinder */ + int trans; /* transfer speed code */ + int heads; /* number of heads */ + int f_gap; /* format gap len */ + int f_inter; /* format interleave factor */ +}; + +#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */ +#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */ +#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */ + +#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */ +#define FD_SOPTS _IOW('F', 65, int) + +#define FD_DEBUG _IOW('F', 66, int) + +#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */ + +/* + * The following definitions duplicate those in sys/i386/isa/fdreg.h + * They are here since their values are to be used in the above + * structure when formatting a floppy. For very obvious reasons, both + * definitions must match ;-) + */ +#ifndef FDC_500KBPS +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + /* for some controllers 1MPBS instead */ +#endif /* FDC_500KBPS */ + +#endif /* !_MACHINE_IOCTL_FD_H_ */ diff --git a/sys/ia64/include/ioctl_meteor.h b/sys/ia64/include/ioctl_meteor.h new file mode 100644 index 0000000..f62d392 --- /dev/null +++ b/sys/ia64/include/ioctl_meteor.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1995 Mark Tinguely and Jim Lowe + * 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 Mark Tinguely and Jim Lowe + * 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. + * + * $FreeBSD$ + */ +/* + * ioctl constants for Matrox Meteor Capture card. + */ + +#ifndef _MACHINE_IOCTL_METEOR_H_ +#define _MACHINE_IOCTL_METEOR_H_ + +#ifndef _KERNEL +#include <sys/types.h> +#endif +#include <sys/ioccom.h> + +struct meteor_capframe { + short command; /* see below for valid METEORCAPFRM commands */ + short lowat; /* start transfer if < this number */ + short hiwat; /* stop transfer if > this number */ +} ; + +/* structure for METEOR[GS]ETGEO - get/set geometry */ +struct meteor_geomet { + u_short rows; + u_short columns; + u_short frames; + u_long oformat; +} ; + +/* structure for METEORGCOUNT-get count of frames, fifo errors and dma errors */ +struct meteor_counts { + u_long fifo_errors; /* count of fifo errors since open */ + u_long dma_errors; /* count of dma errors since open */ + u_long frames_captured; /* count of frames captured since open */ + u_long even_fields_captured; /* count of even fields captured */ + u_long odd_fields_captured; /* count of odd fields captured */ +} ; + +/* structure for getting and setting direct transfers to vram */ +struct meteor_video { + u_long addr; /* Address of location to dma to */ + u_long width; /* Width of memory area */ + u_long banksize; /* Size of Vram bank */ + u_long ramsize; /* Size of Vram */ +}; + +#define METEORCAPTUR _IOW('x', 1, int) /* capture a frame */ +#define METEORCAPFRM _IOW('x', 2, struct meteor_capframe) /* sync capture */ +#define METEORSETGEO _IOW('x', 3, struct meteor_geomet) /* set geometry */ +#define METEORGETGEO _IOR('x', 4, struct meteor_geomet) /* get geometry */ +#define METEORSTATUS _IOR('x', 5, unsigned short) /* get status */ +#define METEORSHUE _IOW('x', 6, signed char) /* set hue */ +#define METEORGHUE _IOR('x', 6, signed char) /* get hue */ +#define METEORSFMT _IOW('x', 7, unsigned long) /* set format */ +#define METEORGFMT _IOR('x', 7, unsigned long) /* get format */ +#define METEORSINPUT _IOW('x', 8, unsigned long) /* set input dev */ +#define METEORGINPUT _IOR('x', 8, unsigned long) /* get input dev */ +#define METEORSCHCV _IOW('x', 9, unsigned char) /* set uv gain */ +#define METEORGCHCV _IOR('x', 9, unsigned char) /* get uv gain */ +#define METEORSCOUNT _IOW('x',10, struct meteor_counts) +#define METEORGCOUNT _IOR('x',10, struct meteor_counts) +#define METEORSFPS _IOW('x',11, unsigned short) /* set fps */ +#define METEORGFPS _IOR('x',11, unsigned short) /* get fps */ +#define METEORSSIGNAL _IOW('x', 12, unsigned int) /* set signal */ +#define METEORGSIGNAL _IOR('x', 12, unsigned int) /* get signal */ +#define METEORSVIDEO _IOW('x', 13, struct meteor_video) /* set video */ +#define METEORGVIDEO _IOR('x', 13, struct meteor_video) /* get video */ +#define METEORSBRIG _IOW('x', 14, unsigned char) /* set brightness */ +#define METEORGBRIG _IOR('x', 14, unsigned char) /* get brightness */ +#define METEORSCSAT _IOW('x', 15, unsigned char) /* set chroma sat */ +#define METEORGCSAT _IOR('x', 15, unsigned char) /* get uv saturation */ +#define METEORSCONT _IOW('x', 16, unsigned char) /* set contrast */ +#define METEORGCONT _IOR('x', 16, unsigned char) /* get contrast */ +#define METEORSBT254 _IOW('x', 17, unsigned short) /* set Bt254 reg */ +#define METEORGBT254 _IOR('x', 17, unsigned short) /* get Bt254 reg */ +#define METEORSHWS _IOW('x', 18, unsigned char) /* set hor start reg */ +#define METEORGHWS _IOR('x', 18, unsigned char) /* get hor start reg */ +#define METEORSVWS _IOW('x', 19, unsigned char) /* set vert start reg */ +#define METEORGVWS _IOR('x', 19, unsigned char) /* get vert start reg */ +#define METEORSTS _IOW('x', 20, unsigned char) /* set time stamp */ +#define METEORGTS _IOR('x', 20, unsigned char) /* get time stamp */ + +#define METEOR_STATUS_ID_MASK 0xf000 /* ID of 7196 */ +#define METEOR_STATUS_DIR 0x0800 /* Direction of Expansion port YUV */ +#define METEOR_STATUS_OEF 0x0200 /* Field detected: Even/Odd */ +#define METEOR_STATUS_SVP 0x0100 /* State of VRAM Port:inactive/active */ +#define METEOR_STATUS_STTC 0x0080 /* Time Constant: TV/VCR */ +#define METEOR_STATUS_HCLK 0x0040 /* Horiz PLL: locked/unlocked */ +#define METEOR_STATUS_FIDT 0x0020 /* Field detect: 50/60hz */ +#define METEOR_STATUS_ALTD 0x0002 /* Line alt: no line alt/line alt */ +#define METEOR_STATUS_CODE 0x0001 /* Colour info: no colour/colour */ + + /* METEORCAPTUR capture options */ +#define METEOR_CAP_SINGLE 0x0001 /* capture one frame */ +#define METEOR_CAP_CONTINOUS 0x0002 /* continuously capture */ +#define METEOR_CAP_STOP_CONT 0x0004 /* stop the continuous capture */ + + /* METEORCAPFRM capture commands */ +#define METEOR_CAP_N_FRAMES 0x0001 /* capture N frames */ +#define METEOR_CAP_STOP_FRAMES 0x0002 /* stop capture N frames */ +#define METEOR_HALT_N_FRAMES 0x0003 /* halt of capture N frames */ +#define METEOR_CONT_N_FRAMES 0x0004 /* continue after above halt */ + + /* valid video input formats: */ +#define METEOR_FMT_NTSC 0x00100 /* NTSC -- initialized default */ +#define METEOR_FMT_PAL 0x00200 /* PAL */ +#define METEOR_FMT_SECAM 0x00400 /* SECAM */ +#define METEOR_FMT_AUTOMODE 0x00800 /* auto-mode */ +#define METEOR_INPUT_DEV0 0x01000 /* camera input 0 -- default */ +#define METEOR_INPUT_DEV_RCA METEOR_INPUT_DEV0 +#define METEOR_INPUT_DEV1 0x02000 /* camera input 1 */ +#define METEOR_INPUT_DEV2 0x04000 /* camera input 2 */ +#define METEOR_INPUT_DEV3 0x08000 /* camera input 3 */ +#define METEOR_INPUT_DEV_RGB 0x0a000 /* for rgb version of meteor */ +#define METEOR_INPUT_DEV_SVIDEO 0x06000 /* S-video input port */ + + /* valid video output formats: */ +#define METEOR_GEO_RGB16 0x0010000 /* packed -- initialized default */ +#define METEOR_GEO_RGB24 0x0020000 /* RBG 24 bits packed */ + /* internally stored in 32 bits */ +#define METEOR_GEO_YUV_PACKED 0x0040000 /* 4-2-2 YUV 16 bits packed */ +#define METEOR_GEO_YUV_PLANAR 0x0080000 /* 4-2-2 YUV 16 bits planer */ +#define METEOR_GEO_YUV_PLANER METEOR_GEO_YUV_PLANAR +#define METEOR_GEO_UNSIGNED 0x0400000 /* unsigned uv outputs */ +#define METEOR_GEO_EVEN_ONLY 0x1000000 /* set for even only field capture */ +#define METEOR_GEO_ODD_ONLY 0x2000000 /* set for odd only field capture */ +#define METEOR_GEO_FIELD_MASK 0x3000000 +#define METEOR_GEO_YUV_422 0x4000000 /* 4-2-2 YUV in Y-U-V combined */ +#define METEOR_GEO_OUTPUT_MASK 0x40f0000 +#define METEOR_GEO_YUV_12 0x10000000 /* YUV 12 format */ +#define METEOR_GEO_YUV_9 0x40000000 /* YUV 9 format */ + +#define METEOR_FIELD_MODE 0x80000000 /* Field cap or Frame cap */ + +#define METEOR_SIG_MODE_MASK 0xffff0000 +#define METEOR_SIG_FRAME 0x00000000 /* signal every frame */ +#define METEOR_SIG_FIELD 0x00010000 /* signal every field */ + + /* following structure is used to coordinate the synchronous */ + +struct meteor_mem { + /* kernel write only */ + int frame_size; /* row*columns*depth */ + unsigned num_bufs; /* number of frames in buffer (1-32) */ + /* user and kernel change these */ + int lowat; /* kernel starts capture if < this number */ + int hiwat; /* kernel stops capture if > this number. + hiwat <= numbufs */ + unsigned active; /* bit mask of active frame buffers + kernel sets, user clears */ + int num_active_bufs; /* count of active frame buffer + kernel increments, user decrements */ + + /* reference to mmapped data */ + caddr_t buf; /* The real space (virtual addr) */ +} ; + +#endif /* !_MACHINE_IOCTL_METEOR_H_ */ diff --git a/sys/ia64/include/ipl.h b/sys/ia64/include/ipl.h new file mode 100644 index 0000000..2a021eb --- /dev/null +++ b/sys/ia64/include/ipl.h @@ -0,0 +1,132 @@ +/*- + * 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_IPL_H_ +#define _MACHINE_IPL_H_ + + +#include <machine/cpu.h> /* for pal inlines */ + +/* + * Software interrupt bit numbers + */ +#define SWI_TTY 0 +#define SWI_NET 1 +#define SWI_CAMNET 2 +#define SWI_CAMBIO 3 +#define SWI_VM 4 +#define SWI_CLOCK 5 +#define SWI_TQ 6 +#define NSWI 32 +#define NHWI 0 + +extern u_int32_t ipending; + +#define getcpl() (alpha_pal_rdps() & ALPHA_PSL_IPL_MASK) + +#define SPLDOWN(name, pri) \ + \ +static __inline int name(void) \ +{ \ + return 0; \ +} + +SPLDOWN(splsoftclock, SOFT) +SPLDOWN(splsoft, SOFT) + +#define SPLUP(name, pri) \ + \ +static __inline int name(void) \ +{ \ + return 0; \ +} + +SPLUP(splsoftcam, SOFT) +SPLUP(splsoftnet, SOFT) +SPLUP(splsoftvm, SOFT) +SPLUP(splsofttq, SOFT) +SPLUP(splnet, IO) +SPLUP(splbio, IO) +SPLUP(splcam, IO) +SPLUP(splimp, IO) +SPLUP(spltty, IO) +SPLUP(splvm, IO) +SPLUP(splclock, CLOCK) +SPLUP(splstatclock, CLOCK) +SPLUP(splhigh, HIGH) + +static __inline void +spl0(void) +{ + if (ipending) + do_sir(); /* lowers ipl to SOFT */ +} + +static __inline void +splx(int s) +{ +} + +extern void setdelayed(void); +extern void setsofttty(void); +extern void setsoftnet(void); +extern void setsoftcamnet(void); +extern void setsoftcambio(void); +extern void setsoftvm(void); +extern void setsofttq(void); +extern void setsoftclock(void); + +extern void schedsofttty(void); +extern void schedsoftnet(void); +extern void schedsoftcamnet(void); +extern void schedsoftcambio(void); +extern void schedsoftvm(void); +extern void schedsofttq(void); +extern void schedsoftclock(void); + +#if 0 +/* XXX bogus */ +extern unsigned cpl; /* current priority level mask */ +#endif + +/* + * Interprocessor interrupts for SMP. + */ +#define IPI_INVLTLB 0x0001 +#define IPI_RENDEZVOUS 0x0002 +#define IPI_AST 0x0004 +#define IPI_CHECKSTATE 0x0008 +#define IPI_STOP 0x0010 + +void smp_ipi_selected(u_int32_t cpus, u_int64_t ipi); +void smp_ipi_all(u_int64_t ipi); +void smp_ipi_all_but_self(u_int64_t ipi); +void smp_ipi_self(u_int64_t ipi); +void smp_handle_ipi(struct trapframe *frame); + +#endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/ia64/include/limits.h b/sys/ia64/include/limits.h new file mode 100644 index 0000000..99ca2d8 --- /dev/null +++ b/sys/ia64/include/limits.h @@ -0,0 +1,96 @@ +/* $FreeBSD$ */ +/* From: NetBSD: limits.h,v 1.3 1997/04/06 08:47:31 cgd Exp */ + +/* + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#define CHAR_BIT 8 /* number of bits in a char */ +#define MB_LEN_MAX 6 /* Allow 31 bit UTF2 */ + +/* + * 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 and LONG_MIN is so the value is not unsigned; 2147483648 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + * These numbers work for pcc as well. The UINT_MAX and ULONG_MAX values + * are written as hex so that GCC will be quiet about large integer constants. + */ +#define SCHAR_MAX 0x7f /* max value for a signed char */ +#define SCHAR_MIN (-0x7f-1) /* min value for a signed char */ + +#define UCHAR_MAX 0xffU /* max value for an unsigned char */ +#define CHAR_MAX 0x7f /* max value for a char */ +#define CHAR_MIN (-0x7f-1) /* min value for a char */ + +#define USHRT_MAX 0xffffU /* 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 */ + +#define ULONG_MAX 0xffffffffffffffffUL /* max for an unsigned long */ +#define LONG_MAX 0x7fffffffffffffffL /* max for a long */ +#define LONG_MIN (-0x7fffffffffffffffL-1) /* min for a long */ + +#if !defined(_ANSI_SOURCE) +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ + +#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t */ + +/* Quads and longs are the same on the alpha */ +#define UQUAD_MAX (ULONG_MAX) /* max value for a uquad_t */ +#define QUAD_MAX (LONG_MAX) /* max value for a quad_t */ +#define QUAD_MIN (LONG_MIN) /* min value for a quad_t */ + +#endif /* !_POSIX_SOURCE && !_XOPEN_SOURCE */ +#endif /* !_ANSI_SOURCE */ + +#if (!defined(_ANSI_SOURCE)&&!defined(_POSIX_SOURCE)) || defined(_XOPEN_SOURCE) +#define LONG_BIT 64 +#define WORD_BIT 32 + +#define DBL_DIG 15 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MIN 2.2250738585072014E-308 + +#define FLT_DIG 6 +#define FLT_MAX 3.40282347E+38F +#define FLT_MIN 1.17549435E-38F +#endif diff --git a/sys/ia64/include/lock.h b/sys/ia64/include/lock.h new file mode 100644 index 0000000..189b966 --- /dev/null +++ b/sys/ia64/include/lock.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997, by Steve Passe + * 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. The name of the developer may NOT be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + + +#ifndef _MACHINE_LOCK_H_ +#define _MACHINE_LOCK_H_ + + +/* + * Simple spin lock. + * It is an error to hold one of these locks while a process is sleeping. + */ +struct simplelock { + volatile int lock_data; +}; + +/* functions in mp_machdep.c */ +void s_lock_init __P((struct simplelock *)); +void s_lock __P((struct simplelock *)); +int s_lock_try __P((struct simplelock *)); + +/* inline simplelock functions */ +static __inline void +s_unlock(struct simplelock *lkp) +{ +#if 0 /* XXX */ + ia64_st_rel_32(&lkp->lock_data, 0); +#endif +} + +#define COM_LOCK() +#define COM_UNLOCK() + +#endif /* !_MACHINE_LOCK_H_ */ diff --git a/sys/ia64/include/md_var.h b/sys/ia64/include/md_var.h new file mode 100644 index 0000000..eeaff20 --- /dev/null +++ b/sys/ia64/include/md_var.h @@ -0,0 +1,57 @@ +/*- + * 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 int Maxmem; +extern void (*netisrs[32]) __P((void)); + +struct fpreg; +struct proc; +struct reg; + +void busdma_swi __P((void)); +void cpu_halt __P((void)); +void cpu_reset __P((void)); +int is_physical_memory __P((vm_offset_t addr)); +void swi_vm __P((void)); +int vm_page_zero_idle __P((void)); +int fill_regs __P((struct proc *, struct reg *)); +int set_regs __P((struct proc *, struct reg *)); +int fill_fpregs __P((struct proc *, struct fpreg *)); +int set_fpregs __P((struct proc *, struct fpreg *)); + +#endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/ia64/include/mouse.h b/sys/ia64/include/mouse.h new file mode 100644 index 0000000..1f9d63b --- /dev/null +++ b/sys/ia64/include/mouse.h @@ -0,0 +1,336 @@ +/*- + * Copyright (c) 1992, 1993 Erik Forsberg. + * Copyright (c) 1996, 1997 Kazutaka YOKOTA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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$ + * from: i386/include mouse.h,v 1.10 + */ + +#ifndef _MACHINE_MOUSE_H_ +#define _MACHINE_MOUSE_H_ + +#include <sys/types.h> +#include <sys/ioccom.h> + +/* ioctls */ +#define MOUSE_GETSTATUS _IOR('M', 0, mousestatus_t) +#define MOUSE_GETHWINFO _IOR('M', 1, mousehw_t) +#define MOUSE_GETMODE _IOR('M', 2, mousemode_t) +#define MOUSE_SETMODE _IOW('M', 3, mousemode_t) +#define MOUSE_GETLEVEL _IOR('M', 4, int) +#define MOUSE_SETLEVEL _IOW('M', 5, int) +#define MOUSE_GETVARS _IOR('M', 6, mousevar_t) +#define MOUSE_SETVARS _IOW('M', 7, mousevar_t) +#define MOUSE_READSTATE _IOWR('M', 8, mousedata_t) +#define MOUSE_READDATA _IOWR('M', 9, mousedata_t) + +#if notyet +#define MOUSE_SETRESOLUTION _IOW('M', 10, int) +#define MOUSE_SETSCALING _IOW('M', 11, int) +#define MOUSE_SETRATE _IOW('M', 12, int) +#define MOUSE_GETHWID _IOR('M', 13, int) +#endif + +/* mouse status block */ +typedef struct mousestatus { + int flags; /* state change flags */ + int button; /* button status */ + int obutton; /* previous button status */ + int dx; /* x movement */ + int dy; /* y movement */ + int dz; /* z movement */ +} mousestatus_t; + +/* button */ +#define MOUSE_BUTTON1DOWN 0x0001 /* left */ +#define MOUSE_BUTTON2DOWN 0x0002 /* middle */ +#define MOUSE_BUTTON3DOWN 0x0004 /* right */ +#define MOUSE_BUTTON4DOWN 0x0008 +#define MOUSE_BUTTON5DOWN 0x0010 +#define MOUSE_BUTTON6DOWN 0x0020 +#define MOUSE_BUTTON7DOWN 0x0040 +#define MOUSE_BUTTON8DOWN 0x0080 +#define MOUSE_MAXBUTTON 31 +#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ +#define MOUSE_EXTBUTTONS 0x7ffffff8 /* the others (28 of them!) */ +#define MOUSE_BUTTONS (MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS) + +/* flags */ +#define MOUSE_STDBUTTONSCHANGED MOUSE_STDBUTTONS +#define MOUSE_EXTBUTTONSCHANGED MOUSE_EXTBUTTONS +#define MOUSE_BUTTONSCHANGED MOUSE_BUTTONS +#define MOUSE_POSCHANGED 0x80000000 + +typedef struct mousehw { + int buttons; /* -1 if unknown */ + int iftype; /* MOUSE_IF_XXX */ + int type; /* mouse/track ball/pad... */ + int model; /* I/F dependent model ID: MOUSE_MODEL_XXX */ + int hwid; /* I/F dependent hardware ID + * for the PS/2 mouse, it will be PSM_XXX_ID + */ +} mousehw_t; + +/* iftype */ +#define MOUSE_IF_UNKNOWN (-1) +#define MOUSE_IF_SERIAL 0 +#define MOUSE_IF_BUS 1 +#define MOUSE_IF_INPORT 2 +#define MOUSE_IF_PS2 3 +#define MOUSE_IF_SYSMOUSE 4 +#define MOUSE_IF_USB 5 + +/* type */ +#define MOUSE_UNKNOWN (-1) /* should be treated as a mouse */ +#define MOUSE_MOUSE 0 +#define MOUSE_TRACKBALL 1 +#define MOUSE_STICK 2 +#define MOUSE_PAD 3 + +/* model */ +#define MOUSE_MODEL_UNKNOWN (-1) +#define MOUSE_MODEL_GENERIC 0 +#define MOUSE_MODEL_GLIDEPOINT 1 +#define MOUSE_MODEL_NETSCROLL 2 +#define MOUSE_MODEL_NET 3 +#define MOUSE_MODEL_INTELLI 4 +#define MOUSE_MODEL_THINK 5 +#define MOUSE_MODEL_EASYSCROLL 6 +#define MOUSE_MODEL_MOUSEMANPLUS 7 +#define MOUSE_MODEL_KIDSPAD 8 +#define MOUSE_MODEL_VERSAPAD 9 +#define MOUSE_MODEL_EXPLORER 10 +#define MOUSE_MODEL_4D 11 +#define MOUSE_MODEL_4DPLUS 12 + +typedef struct mousemode { + int protocol; /* MOUSE_PROTO_XXX */ + int rate; /* report rate (per sec), -1 if unknown */ + int resolution; /* MOUSE_RES_XXX, -1 if unknown */ + int accelfactor; /* accelation factor (must be 1 or greater) */ + int level; /* driver operation level */ + int packetsize; /* the length of the data packet */ + unsigned char syncmask[2]; /* sync. data bits in the header byte */ +} mousemode_t; + +/* protocol */ +/* + * Serial protocols: + * Microsoft, MouseSystems, Logitech, MM series, MouseMan, Hitachi Tablet, + * GlidePoint, IntelliMouse, Thinking Mouse, MouseRemote, Kidspad, + * VersaPad + * Bus mouse protocols: + * bus, InPort + * PS/2 mouse protocol: + * PS/2 + */ +#define MOUSE_PROTO_UNKNOWN (-1) +#define MOUSE_PROTO_MS 0 /* Microsoft Serial, 3 bytes */ +#define MOUSE_PROTO_MSC 1 /* Mouse Systems, 5 bytes */ +#define MOUSE_PROTO_LOGI 2 /* Logitech, 3 bytes */ +#define MOUSE_PROTO_MM 3 /* MM series, 3 bytes */ +#define MOUSE_PROTO_LOGIMOUSEMAN 4 /* Logitech MouseMan 3/4 bytes */ +#define MOUSE_PROTO_BUS 5 /* MS/Logitech bus mouse */ +#define MOUSE_PROTO_INPORT 6 /* MS/ATI InPort mouse */ +#define MOUSE_PROTO_PS2 7 /* PS/2 mouse, 3 bytes */ +#define MOUSE_PROTO_HITTAB 8 /* Hitachi Tablet 3 bytes */ +#define MOUSE_PROTO_GLIDEPOINT 9 /* ALPS GlidePoint, 3/4 bytes */ +#define MOUSE_PROTO_INTELLI 10 /* MS IntelliMouse, 4 bytes */ +#define MOUSE_PROTO_THINK 11 /* Kensignton Thinking Mouse, 3/4 bytes */ +#define MOUSE_PROTO_SYSMOUSE 12 /* /dev/sysmouse */ +#define MOUSE_PROTO_X10MOUSEREM 13 /* X10 MouseRemote, 3 bytes */ +#define MOUSE_PROTO_KIDSPAD 14 /* Genius Kidspad */ +#define MOUSE_PROTO_VERSAPAD 15 /* Interlink VersaPad, 6 bytes */ + +#define MOUSE_RES_UNKNOWN (-1) +#define MOUSE_RES_DEFAULT 0 +#define MOUSE_RES_LOW (-2) +#define MOUSE_RES_MEDIUMLOW (-3) +#define MOUSE_RES_MEDIUMHIGH (-4) +#define MOUSE_RES_HIGH (-5) + +typedef struct mousedata { + int len; /* # of data in the buffer */ + int buf[16]; /* data buffer */ +} mousedata_t; + +#if (defined(MOUSE_GETVARS)) + +typedef struct mousevar { + int var[16]; +} mousevar_t; + +/* magic numbers in var[0] */ +#define MOUSE_VARS_PS2_SIG 0x00325350 /* 'PS2' */ +#define MOUSE_VARS_BUS_SIG 0x00535542 /* 'BUS' */ +#define MOUSE_VARS_INPORT_SIG 0x00504e49 /* 'INP' */ + +#endif /* MOUSE_GETVARS */ + +/* Microsoft Serial mouse data packet */ +#define MOUSE_MSS_PACKETSIZE 3 +#define MOUSE_MSS_SYNCMASK 0x40 +#define MOUSE_MSS_SYNC 0x40 +#define MOUSE_MSS_BUTTONS 0x30 +#define MOUSE_MSS_BUTTON1DOWN 0x20 /* left */ +#define MOUSE_MSS_BUTTON2DOWN 0x00 /* no middle button */ +#define MOUSE_MSS_BUTTON3DOWN 0x10 /* right */ + +/* Logitech MouseMan data packet (M+ protocol) */ +#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ + +/* ALPS GlidePoint extention (variant of M+ protocol) */ +#define MOUSE_ALPS_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ +#define MOUSE_ALPS_TAP 0x10 /* `tapping' action, the 4th byte */ + +/* Kinsington Thinking Mouse extention (variant of M+ protocol) */ +#define MOUSE_THINK_BUTTON2DOWN 0x20 /* lower-left button, the 4th byte */ +#define MOUSE_THINK_BUTTON4DOWN 0x10 /* lower-right button, the 4th byte */ + +/* MS IntelliMouse (variant of MS Serial) */ +#define MOUSE_INTELLI_PACKETSIZE 4 +#define MOUSE_INTELLI_BUTTON2DOWN 0x10 /* middle button in the 4th byte */ + +/* Mouse Systems Corp. mouse data packet */ +#define MOUSE_MSC_PACKETSIZE 5 +#define MOUSE_MSC_SYNCMASK 0xf8 +#define MOUSE_MSC_SYNC 0x80 +#define MOUSE_MSC_BUTTONS 0x07 +#define MOUSE_MSC_BUTTON1UP 0x04 /* left */ +#define MOUSE_MSC_BUTTON2UP 0x02 /* middle */ +#define MOUSE_MSC_BUTTON3UP 0x01 /* right */ +#define MOUSE_MSC_MAXBUTTON 3 + +/* MM series mouse data packet */ +#define MOUSE_MM_PACKETSIZE 3 +#define MOUSE_MM_SYNCMASK 0xe0 +#define MOUSE_MM_SYNC 0x80 +#define MOUSE_MM_BUTTONS 0x07 +#define MOUSE_MM_BUTTON1DOWN 0x04 /* left */ +#define MOUSE_MM_BUTTON2DOWN 0x02 /* middle */ +#define MOUSE_MM_BUTTON3DOWN 0x01 /* right */ +#define MOUSE_MM_XPOSITIVE 0x10 +#define MOUSE_MM_YPOSITIVE 0x08 + +/* PS/2 mouse data packet */ +#define MOUSE_PS2_PACKETSIZE 3 +#define MOUSE_PS2_SYNCMASK 0xc8 +#define MOUSE_PS2_SYNC 0x08 +#define MOUSE_PS2_BUTTONS 0x07 /* 0x03 for 2 button mouse */ +#define MOUSE_PS2_BUTTON1DOWN 0x01 /* left */ +#define MOUSE_PS2_BUTTON2DOWN 0x04 /* middle */ +#define MOUSE_PS2_BUTTON3DOWN 0x02 /* right */ +#define MOUSE_PS2_TAP MOUSE_PS2_SYNC /* GlidePoint (PS/2) `tapping' + * Yes! this is the same bit + * as SYNC! + */ + +#define MOUSE_PS2_XNEG 0x10 +#define MOUSE_PS2_YNEG 0x20 +#define MOUSE_PS2_XOVERFLOW 0x40 +#define MOUSE_PS2_YOVERFLOW 0x80 + +/* Logitech MouseMan+ (PS/2) data packet (PS/2++ protocol) */ +#define MOUSE_PS2PLUS_SYNCMASK 0x48 +#define MOUSE_PS2PLUS_SYNC 0x48 +#define MOUSE_PS2PLUS_ZNEG 0x08 /* sign bit */ +#define MOUSE_PS2PLUS_BUTTON4DOWN 0x10 /* 4th button on MouseMan+ */ +#define MOUSE_PS2PLUS_BUTTON5DOWN 0x20 + +/* IBM ScrollPoint (PS/2) also uses PS/2++ protocol */ +#define MOUSE_SPOINT_ZNEG 0x80 /* sign bits */ +#define MOUSE_SPOINT_WNEG 0x08 + +/* MS IntelliMouse (PS/2) data packet */ +#define MOUSE_PS2INTELLI_PACKETSIZE 4 +/* some compatible mice have additional buttons */ +#define MOUSE_PS2INTELLI_BUTTON4DOWN 0x40 +#define MOUSE_PS2INTELLI_BUTTON5DOWN 0x80 + +/* MS IntelliMouse Explorer (PS/2) data packet (variation of IntelliMouse) */ +#define MOUSE_EXPLORER_ZNEG 0x08 /* sign bit */ +/* IntelliMouse Explorer has additional button data in the fourth byte */ +#define MOUSE_EXPLORER_BUTTON4DOWN 0x10 +#define MOUSE_EXPLORER_BUTTON5DOWN 0x20 + +/* Interlink VersaPad (serial I/F) data packet */ +#define MOUSE_VERSA_PACKETSIZE 6 +#define MOUSE_VERSA_IN_USE 0x04 +#define MOUSE_VERSA_SYNCMASK 0xc3 +#define MOUSE_VERSA_SYNC 0xc0 +#define MOUSE_VERSA_BUTTONS 0x30 +#define MOUSE_VERSA_BUTTON1DOWN 0x20 /* left */ +#define MOUSE_VERSA_BUTTON2DOWN 0x00 /* middle */ +#define MOUSE_VERSA_BUTTON3DOWN 0x10 /* right */ +#define MOUSE_VERSA_TAP 0x08 + +/* Interlink VersaPad (PS/2 I/F) data packet */ +#define MOUSE_PS2VERSA_PACKETSIZE 6 +#define MOUSE_PS2VERSA_IN_USE 0x10 +#define MOUSE_PS2VERSA_SYNCMASK 0xe8 +#define MOUSE_PS2VERSA_SYNC 0xc8 +#define MOUSE_PS2VERSA_BUTTONS 0x05 +#define MOUSE_PS2VERSA_BUTTON1DOWN 0x04 /* left */ +#define MOUSE_PS2VERSA_BUTTON2DOWN 0x00 /* middle */ +#define MOUSE_PS2VERSA_BUTTON3DOWN 0x01 /* right */ +#define MOUSE_PS2VERSA_TAP 0x02 + +/* A4 Tech 4D Mouse (PS/2) data packet */ +#define MOUSE_4D_PACKETSIZE 3 +#define MOUSE_4D_WHEELBITS 0xf0 + +/* A4 Tech 4D+ Mouse (PS/2) data packet */ +#define MOUSE_4DPLUS_PACKETSIZE 3 +#define MOUSE_4DPLUS_ZNEG 0x04 /* sign bit */ +#define MOUSE_4DPLUS_BUTTON4DOWN 0x08 + +/* sysmouse extended data packet */ +/* + * /dev/sysmouse sends data in two formats, depending on the protocol + * level. At the level 0, format is exactly the same as MousSystems' + * five byte packet. At the level 1, the first five bytes are the same + * as at the level 0. There are additional three bytes which shows + * `dz' and the states of additional buttons. `dz' is expressed as the + * sum of the byte 5 and 6 which contain signed seven bit values. + * The states of the button 4 though 10 are in the bit 0 though 6 in + * the byte 7 respectively: 1 indicates the button is up. + */ +#define MOUSE_SYS_PACKETSIZE 8 +#define MOUSE_SYS_SYNCMASK 0xf8 +#define MOUSE_SYS_SYNC 0x80 +#define MOUSE_SYS_BUTTON1UP 0x04 /* left, 1st byte */ +#define MOUSE_SYS_BUTTON2UP 0x02 /* middle, 1st byte */ +#define MOUSE_SYS_BUTTON3UP 0x01 /* right, 1st byte */ +#define MOUSE_SYS_BUTTON4UP 0x0001 /* 7th byte */ +#define MOUSE_SYS_BUTTON5UP 0x0002 +#define MOUSE_SYS_BUTTON6UP 0x0004 +#define MOUSE_SYS_BUTTON7UP 0x0008 +#define MOUSE_SYS_BUTTON8UP 0x0010 +#define MOUSE_SYS_BUTTON9UP 0x0020 +#define MOUSE_SYS_BUTTON10UP 0x0040 +#define MOUSE_SYS_MAXBUTTON 10 +#define MOUSE_SYS_STDBUTTONS 0x07 +#define MOUSE_SYS_EXTBUTTONS 0x7f /* the others */ + +/* Mouse remote socket */ +#define _PATH_MOUSEREMOTE "/var/run/MouseRemote" + +#endif /* _MACHINE_MOUSE_H_ */ diff --git a/sys/ia64/include/mutex.h b/sys/ia64/include/mutex.h new file mode 100644 index 0000000..b858079 --- /dev/null +++ b/sys/ia64/include/mutex.h @@ -0,0 +1,563 @@ +/*- + * 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_ + +#ifndef LOCORE + +#include <sys/ktr.h> +#include <sys/queue.h> +#include <machine/atomic.h> +#include <machine/cpufunc.h> +#include <machine/globaldata.h> +#include <machine/globals.h> + +/* + * If kern_mutex.c is being built, compile non-inlined versions of various + * functions so that kernel modules can use them. + */ +#ifndef _KERN_MUTEX_C_ +#define _MTX_INLINE static __inline +#else +#define _MTX_INLINE +#endif + +/* + * Mutex flags + * + * Types + */ +#define MTX_DEF 0x1 /* Default (spin/sleep) */ +#define MTX_SPIN 0x2 /* Spin only lock */ + +/* Options */ +#define MTX_RLIKELY 0x4 /* (opt) Recursion likely */ +#define MTX_NORECURSE 0x8 /* No recursion possible */ +#define MTX_NOSPIN 0x10 /* Don't spin before sleeping */ +#define MTX_NOSWITCH 0x20 /* Do not switch on release */ +#define MTX_FIRST 0x40 /* First spin lock holder */ +#define MTX_TOPHALF 0x80 /* Interrupts not disabled on spin */ + +/* options that should be passed on to mtx_enter_hard, mtx_exit_hard */ +#define MTX_HARDOPTS (MTX_DEF | MTX_SPIN | MTX_FIRST | MTX_TOPHALF | MTX_NOSWITCH) + +/* Flags/value used in mtx_lock */ +#define MTX_RECURSE 0x01 /* (non-spin) lock held recursively */ +#define MTX_CONTESTED 0x02 /* (non-spin) lock contested */ +#define MTX_FLAGMASK ~(MTX_RECURSE | MTX_CONTESTED) +#define MTX_UNOWNED 0x8 /* Cookie for free mutex */ + +struct proc; /* XXX */ + +/* + * Sleep/spin mutex + */ +struct mtx { + volatile u_int64_t mtx_lock; /* lock owner/gate/flags */ + volatile u_int32_t mtx_recurse; /* number of recursive holds */ + u_int32_t mtx_savepsr; /* saved psr (for spin locks) */ + char *mtx_description; + TAILQ_HEAD(, proc) mtx_blocked; + LIST_ENTRY(mtx) mtx_contested; + struct mtx *mtx_next; /* all locks in system */ + struct mtx *mtx_prev; +#ifdef SMP_DEBUG + /* If you add anything here, adjust the mtxf_t definition below */ + struct witness *mtx_witness; + LIST_ENTRY(mtx) mtx_held; + const char *mtx_file; + int mtx_line; +#endif /* SMP_DEBUG */ +}; + +/* + * Filler for structs which need to remain the same size + * whether or not SMP_DEBUG is turned on. + */ +typedef struct mtxf { +#ifdef SMP_DEBUG + char mtxf_data[0]; +#else + char mtxf_data[4*sizeof(void *) + sizeof(int)]; +#endif +} mtxf_t; + +#define mp_fixme(string) + +#ifdef _KERNEL +/* Misc */ +#define CURTHD ((u_int64_t)CURPROC) /* Current thread ID */ + +/* Prototypes */ +void mtx_init(struct mtx *m, char *description, int flag); +void mtx_enter_hard(struct mtx *, int type, int psr); +void mtx_exit_hard(struct mtx *, int type); +void mtx_destroy(struct mtx *m); + +/* + * Wrap the following functions with cpp macros so that filenames and line + * numbers are embedded in the code correctly. + */ +#if (defined(KLD_MODULE) || defined(_KERN_MUTEX_C_)) +void _mtx_enter(struct mtx *mtxp, int type, const char *file, int line); +int _mtx_try_enter(struct mtx *mtxp, int type, const char *file, int line); +void _mtx_exit(struct mtx *mtxp, int type, const char *file, int line); +#endif + +#define mtx_enter(mtxp, type) \ + _mtx_enter((mtxp), (type), __FILE__, __LINE__) + +#define mtx_try_enter(mtxp, type) \ + _mtx_try_enter((mtxp), (type), __FILE__, __LINE__) + +#define mtx_exit(mtxp, type) \ + _mtx_exit((mtxp), (type), __FILE__, __LINE__) + +/* Global locks */ +extern struct mtx sched_lock; +extern struct mtx Giant; + +/* + * Used to replace return with an exit Giant and return. + */ + +#define EGAR(a) \ +do { \ + mtx_exit(&Giant, MTX_DEF); \ + return (a); \ +} while (0) + +#define VEGAR \ +do { \ + mtx_exit(&Giant, MTX_DEF); \ + return; \ +} while (0) + +#define DROP_GIANT() \ +do { \ + int _giantcnt; \ + WITNESS_SAVE_DECL(Giant); \ + \ + WITNESS_SAVE(&Giant, Giant); \ + for (_giantcnt = 0; mtx_owned(&Giant); _giantcnt++) \ + mtx_exit(&Giant, MTX_DEF) + +#define PICKUP_GIANT() \ + mtx_assert(&Giant, MA_NOTOWNED); \ + while (_giantcnt--) \ + mtx_enter(&Giant, MTX_DEF); \ + WITNESS_RESTORE(&Giant, Giant); \ +} while (0) + +#define PARTIAL_PICKUP_GIANT() \ + mtx_assert(&Giant, MA_NOTOWNED); \ + while (_giantcnt--) \ + mtx_enter(&Giant, MTX_DEF); \ + WITNESS_RESTORE(&Giant, Giant) + +/* + * Debugging + */ +#ifndef SMP_DEBUG +#define mtx_assert(m, what) +#else /* SMP_DEBUG */ + +#define MA_OWNED 1 +#define MA_NOTOWNED 2 +#define mtx_assert(m, what) { \ + switch ((what)) { \ + case MA_OWNED: \ + ASS(mtx_owned((m))); \ + break; \ + case MA_NOTOWNED: \ + ASS(!mtx_owned((m))); \ + break; \ + default: \ + panic("unknown mtx_assert at %s:%d", __FILE__, __LINE__); \ + } \ +} + +#ifdef INVARIANTS +#define ASS(ex) MPASS(ex) +#define MPASS(ex) if (!(ex)) panic("Assertion %s failed at %s:%d", \ + #ex, __FILE__, __LINE__) +#define MPASS2(ex, what) if (!(ex)) panic("Assertion %s failed at %s:%d", \ + what, __FILE__, __LINE__) + +#ifdef MTX_STRS +char STR_IEN[] = "psr.i"; +char STR_IDIS[] = "!psr.i"; +#else /* MTX_STRS */ +extern char STR_IEN[]; +extern char STR_IDIS[]; +#endif /* MTX_STRS */ +#define ASS_IEN MPASS2((save_intr() & (1 << 14)), STR_IEN) +#define ASS_IDIS MPASS2(!(save_intr() & (1 << 14)), STR_IDIS) +#endif /* INVARIANTS */ + +#endif /* SMP_DEBUG */ + +#if !defined(SMP_DEBUG) || !defined(INVARIANTS) +#define ASS(ex) +#define MPASS(ex) +#define MPASS2(ex, where) +#define ASS_IEN +#define ASS_IDIS +#endif /* !defined(SMP_DEBUG) || !defined(INVARIANTS) */ + +#ifdef WITNESS +#ifndef SMP_DEBUG +#error WITNESS requires SMP_DEBUG +#endif /* SMP_DEBUG */ +#define WITNESS_ENTER(m, t, f, l) \ + if ((m)->mtx_witness != NULL) \ + witness_enter((m), (t), (f), (l)) +#define WITNESS_EXIT(m, t, f, l) \ + if ((m)->mtx_witness != NULL) \ + witness_exit((m), (t), (f), (l)) + +#define WITNESS_SLEEP(check, m) witness_sleep(check, (m), __FILE__, __LINE__) +#define WITNESS_SAVE_DECL(n) \ + const char * __CONCAT(n, __wf); \ + int __CONCAT(n, __wl) + +#define WITNESS_SAVE(m, n) \ +do { \ + if ((m)->mtx_witness != NULL) \ + witness_save(m, &__CONCAT(n, __wf), &__CONCAT(n, __wl)); \ +} while (0) + +#define WITNESS_RESTORE(m, n) \ +do { \ + if ((m)->mtx_witness != NULL) \ + witness_restore(m, __CONCAT(n, __wf), __CONCAT(n, __wl)); \ +} while (0) + +void witness_init(struct mtx *, int flag); +void witness_destroy(struct mtx *); +void witness_enter(struct mtx *, int, const char *, int); +void witness_try_enter(struct mtx *, int, const char *, int); +void witness_exit(struct mtx *, int, const char *, int); +void witness_display(void(*)(const char *fmt, ...)); +void witness_list(struct proc *); +int witness_sleep(int, struct mtx *, const char *, int); +void witness_save(struct mtx *, const char **, int *); +void witness_restore(struct mtx *, const char *, int); +#else /* WITNESS */ +#define WITNESS_ENTER(m, t, f, l) +#define WITNESS_EXIT(m, t, f, l) +#define WITNESS_SLEEP(check, m) +#define WITNESS_SAVE_DECL(n) +#define WITNESS_SAVE(m, n) +#define WITNESS_RESTORE(m, n) + +/* + * flag++ is slezoid way of shutting up unused parameter warning + * in mtx_init() + */ +#define witness_init(m, flag) flag++ +#define witness_destroy(m) +#define witness_enter(m, t, f, l) +#define witness_try_enter(m, t, f, l) +#define witness_exit(m, t, f, l) +#endif /* WITNESS */ + +/* + * Assembly macros (for internal use only) + *-------------------------------------------------------------------------- + */ + +/* + * Get a sleep lock, deal with recursion inline + */ + +#define _V(x) __STRING(x) + +#define _getlock_sleep(mp, tid, type) do { \ + if (ia64_cmpxchg_acq_64(&(mp)->mtx_lock, \ + MTX_UNOWNED, (tid)) != MTX_UNOWNED) { \ + if (((mp)->mtx_lock & MTX_FLAGMASK) != (tid)) \ + mtx_enter_hard(mp, (type) & MTX_HARDOPTS, 0); \ + else { \ + atomic_set_64(&(mp)->mtx_lock, MTX_RECURSE); \ + (mp)->mtx_recurse++; \ + } \ + } \ +} while (0) + +/* + * Get a spin lock, handle recusion inline (as the less common case) + */ + +#define _getlock_spin_block(mp, tid, type) do { \ + u_int _psr = save_intr(); \ + disable_intr(); \ + if (ia64_cmpxchg_acq_64(&(mp)->mtx_lock, \ + MTX_UNOWNED, (tid)) != MTX_UNOWNED) \ + mtx_enter_hard(mp, (type) & MTX_HARDOPTS, _psr); \ + else \ + (mp)->mtx_savepsr = _psr; \ +} while (0) + +/* + * Get a lock without any recursion handling. Calls the hard enter + * function if we can't get it inline. + */ + +#define _getlock_norecurse(mp, tid, type) do { \ + if (ia64_cmpxchg_acq_64(&(mp)->mtx_lock, \ + MTX_UNOWNED, (tid)) != MTX_UNOWNED) \ + mtx_enter_hard(mp, (type) & MTX_HARDOPTS, 0); \ +} while (0) + +/* + * Release a sleep lock assuming we haven't recursed on it, recursion is + * handled in the hard function. + */ + +#define _exitlock_norecurse(mp, tid, type) do { \ + if (ia64_cmpxchg_rel_64(&(mp)->mtx_lock, \ + (tid), MTX_UNOWNED) != (tid)) \ + mtx_exit_hard((mp), (type) & MTX_HARDOPTS); \ +} while (0) + +/* + * Release a sleep lock when its likely we recursed (the code to + * deal with simple recursion is inline). + */ + +#define _exitlock(mp, tid, type) do { \ + if (ia64_cmpxchg_rel_64(&(mp)->mtx_lock, \ + (tid), MTX_UNOWNED) != (tid)) { \ + if (((mp)->mtx_lock & MTX_RECURSE) && \ + (--(mp)->mtx_recurse == 0)) \ + atomic_clear_64(&(mp)->mtx_lock, MTX_RECURSE); \ + else \ + mtx_exit_hard((mp), (type) & MTX_HARDOPTS); \ + } \ +} while (0) + +/* + * Release a spin lock (with possible recursion) + */ + +#define _exitlock_spin(mp) do { \ + if ((mp)->mtx_recurse == 0) { \ + int _psr = (mp)->mtx_savepsr; \ + ia64_st_rel_64(&(mp)->mtx_lock, MTX_UNOWNED); \ + restore_intr(_psr); \ + } else { \ + (mp)->mtx_recurse--; \ + } \ +} while (0) + +/* + * Externally visible mutex functions + *------------------------------------------------------------------------ + */ + +/* + * Return non-zero if a mutex is already owned by the current thread + */ +#define mtx_owned(m) (((m)->mtx_lock & MTX_FLAGMASK) == CURTHD) + +/* Common strings */ +#ifdef MTX_STRS +char STR_mtx_enter_fmt[] = "GOT %s [%p] at %s:%d r=%d"; +char STR_mtx_bad_type[] = "((type) & (MTX_NORECURSE | MTX_NOSWITCH)) == 0"; +char STR_mtx_exit_fmt[] = "REL %s [%p] at %s:%d r=%d"; +char STR_mtx_owned[] = "mtx_owned(mpp)"; +char STR_mtx_recurse[] = "mpp->mtx_recurse == 0"; +char STR_mtx_try_enter_fmt[] = "TRY_ENTER %s [%p] at %s:%d result=%d"; +#else /* MTX_STRS */ +extern char STR_mtx_enter_fmt[]; +extern char STR_mtx_bad_type[]; +extern char STR_mtx_exit_fmt[]; +extern char STR_mtx_owned[]; +extern char STR_mtx_recurse[]; +extern char STR_mtx_try_enter_fmt[]; +#endif /* MTX_STRS */ + +#ifndef KLD_MODULE +/* + * Get lock 'm', the macro handles the easy (and most common cases) and + * leaves the slow stuff to the mtx_enter_hard() function. + * + * Note: since type is usually a constant much of this code is optimized out + */ +_MTX_INLINE void +_mtx_enter(struct mtx *mtxp, int type, const char *file, int line) +{ + struct mtx *mpp = mtxp; + + /* bits only valid on mtx_exit() */ + MPASS2(((type) & (MTX_NORECURSE | MTX_NOSWITCH)) == 0, + STR_mtx_bad_type); + + if ((type) & MTX_SPIN) { + /* + * Easy cases of spin locks: + * + * 1) We already own the lock and will simply recurse on it (if + * RLIKELY) + * + * 2) The lock is free, we just get it + */ + if ((type) & MTX_RLIKELY) { + /* + * Check for recursion, if we already have this lock we + * just bump the recursion count. + */ + if (mpp->mtx_lock == CURTHD) { + mpp->mtx_recurse++; + goto done; + } + } + + if (((type) & MTX_TOPHALF) == 0) { + /* + * If an interrupt thread uses this we must block + * interrupts here. + */ + _getlock_spin_block(mpp, CURTHD, (type) & MTX_HARDOPTS); + } else + _getlock_norecurse(mpp, CURTHD, (type) & MTX_HARDOPTS); + } else { + /* Sleep locks */ + if ((type) & MTX_RLIKELY) + _getlock_sleep(mpp, CURTHD, (type) & MTX_HARDOPTS); + else + _getlock_norecurse(mpp, CURTHD, (type) & MTX_HARDOPTS); + } + done: + WITNESS_ENTER(mpp, type, file, line); + CTR5(KTR_LOCK, STR_mtx_enter_fmt, + mpp->mtx_description, mpp, file, line, + mpp->mtx_recurse); +} + +/* + * Attempt to get MTX_DEF lock, return non-zero if lock acquired + * + * XXX DOES NOT HANDLE RECURSION + */ +_MTX_INLINE int +_mtx_try_enter(struct mtx *mtxp, int type, const char *file, int line) +{ + struct mtx *const mpp = mtxp; + int rval; + + rval = atomic_cmpset_64(&mpp->mtx_lock, MTX_UNOWNED, CURTHD); +#ifdef SMP_DEBUG + if (rval && mpp->mtx_witness != NULL) { + ASS(mpp->mtx_recurse == 0); + witness_try_enter(mpp, type, file, line); + } +#endif + CTR5(KTR_LOCK, STR_mtx_try_enter_fmt, + mpp->mtx_description, mpp, file, line, rval); + + return rval; +} + +/* + * Release lock m + */ +_MTX_INLINE void +_mtx_exit(struct mtx *mtxp, int type, const char *file, int line) +{ + struct mtx *const mpp = mtxp; + + MPASS2(mtx_owned(mpp), STR_mtx_owned); + WITNESS_EXIT(mpp, type, file, line); + CTR5(KTR_LOCK, STR_mtx_exit_fmt, + mpp->mtx_description, mpp, file, line, + mpp->mtx_recurse); + if ((type) & MTX_SPIN) { + if ((type) & MTX_NORECURSE) { + MPASS2(mpp->mtx_recurse == 0, STR_mtx_recurse); + ia64_st_rel_64(&mpp->mtx_lock, MTX_UNOWNED); + if (((type) & MTX_TOPHALF) == 0) + restore_intr(mpp->mtx_savepsr); + } else + if ((type) & MTX_TOPHALF) { + _exitlock_norecurse(mpp, CURTHD, + (type) & MTX_HARDOPTS); + } else + _exitlock_spin(mpp); + } else { + /* Handle sleep locks */ + if ((type) & MTX_RLIKELY) { + _exitlock(mpp, CURTHD, (type) & MTX_HARDOPTS); + } else { + _exitlock_norecurse(mpp, CURTHD, + (type) & MTX_HARDOPTS); + } + } +} + +#endif /* KLD_MODULE */ +#endif /* _KERNEL */ + +#else /* !LOCORE */ + +/* + * Simple assembly macros to get and release non-recursive spin locks + */ +#define MTX_ENTER(lck, rPSR, rOLD, rNEW, rLCK) \ + mov rPSR=psr ; \ + mov rNEW=globalp ; \ + mov rLCK=lck+MTX_LOCK ;; \ + rsm psr.i ; \ + mov ar.ccv=MTX_UNOWNED ; \ + add rNEW=PC_CURPROC,rNEW ;; \ + ld8 rNEW=[rNEW] ;; \ +1: cmpxchg8.acq rOLD=[rLCK],rNEW,ar.ccv ;; \ + cmp.eq p1,p0=MTX_UNOWNED,rOLD ;; \ +(p1) br.cond.spnt.few 1b ;; \ + mov rLCK=lck+MTX_SAVEPSR ;; \ + st4 [rLCK]=rPSR + +#define MTX_EXIT(lck, rTMP, rLCK) \ + mov rTMP=MTX_UNOWNED ; \ + addl rLCK=@ltoff(lck),gp;; \ + add rLCK=MTX_LOCK,rLCK;; \ + st8.rel [rLCK]=rTMP ;; \ + addl rLCK=@ltoff(lck),gp;; \ + add rLCK=MTX_SAVEPSR,rLCK;; \ + ld4 rTMP=[rLCK] ;; \ + mov psr.l=rTMP ;; \ + srlz.d + +#endif /* !LOCORE */ + +#endif /* __MACHINE_MUTEX_H */ diff --git a/sys/ia64/include/pal.h b/sys/ia64/include/pal.h new file mode 100644 index 0000000..39c12a4 --- /dev/null +++ b/sys/ia64/include/pal.h @@ -0,0 +1,95 @@ +/*- + * 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$ + */ + +#ifndef _MACHINE_PAL_H_ +#define _MACHINE_PAL_H_ + +/* + * Architected static calling convention procedures. + */ +#define PAL_CACHE_FLUSH 1 +#define PAL_CACHE_INFO 2 +#define PAL_CACHE_INIT 3 +#define PAL_CACHE_SUMMARY 4 +#define PAL_MEM_ATTRIB 5 +#define PAL_PTCE_INFO 6 +#define PAL_VM_INFO 7 +#define PAL_VM_SUMMARY 8 +#define PAL_BUS_GET_FEATURES 9 +#define PAL_BUS_SET_FEATURES 10 +#define PAL_DEBUG_INFO 11 +#define PAL_FIXED_ADDR 12 +#define PAL_FREQ_BASE 13 +#define PAL_FREQ_RATIOS 14 +#define PAL_PERF_MON_INFO 15 +#define PAL_PLATFORM_ADDR 16 +#define PAL_PROC_GET_FEATURE 17 +#define PAL_PROC_SET_FEATURE 18 +#define PAL_RSE_INFO 19 +#define PAL_VERSION 20 +#define PAL_MC_CLEAR_LOG 21 +#define PAL_MC_DRAIN 22 +#define PAL_MC_DYNAMIC_STATE 24 +#define PAL_MC_ERROR_INFO 25 +#define PAL_MC_EXPECTED 23 +#define PAL_MC_REGISTER_MEM 27 +#define PAL_MC_RESUME 26 +#define PAL_HALT 28 +#define PAL_HALT_LIGHT 29 +#define PAL_COPY_INFO 30 +#define PAL_CACHE_LINE_INIT 31 +#define PAL_PMI_ENTRYPOINT 32 +#define PAL_ENTER_IA_32_ENV 33 +#define PAL_VM_PAGE_SIZE 34 +#define PAL_MEM_FOR_TEST 37 +#define PAL_CACHE_PROT_INFO 38 +#define PAL_REGISTER_INFO 39 +#define PAL_SHUTDOWN 40 +#define PAL_PREFETCH_VISIBILITY 41 + +/* + * Architected stacked calling convention procedures. + */ +#define PAL_COPY_PAL 256 +#define PAL_HALT_INFO 257 +#define PAL_TEST_PROC 258 +#define PAL_CACHE_READ 259 +#define PAL_CACHE_WRITE 260 +#define PAL_VM_TR_READ 261 + +struct ia64_pal_result { + int64_t pal_status; + u_int64_t pal_result[3]; +}; + +extern struct ia64_pal_result + ia64_call_pal_static(u_int64_t proc, u_int64_t arg1, + u_int64_t arg2, u_int64_t arg3); + + +#endif /* _MACHINE_PAL_H_ */ diff --git a/sys/ia64/include/param.h b/sys/ia64/include/param.h new file mode 100644 index 0000000..d67a0fc --- /dev/null +++ b/sys/ia64/include/param.h @@ -0,0 +1,163 @@ +/* $FreeBSD$ */ +/* From: NetBSD: param.h,v 1.20 1997/09/19 13:52:53 leo Exp */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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: Utah $Hdr: machparam.h 1.11 89/08/14$ + * + * @(#)param.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Machine dependent constants for the IA64. + */ +#ifndef _MACHINE +#define _MACHINE ia64 +#endif +#ifndef MACHINE +#define MACHINE "ia64" +#endif +#ifndef _MACHINE_ARCH +#define _MACHINE_ARCH ia64 +#endif +#ifndef MACHINE_ARCH +#define MACHINE_ARCH "ia64" +#endif +#define MID_MACHINE MID_IA64 + +#include <machine/ia64_cpu.h> +#include <machine/cpu.h> + +/* + * OBJFORMAT_NAMES is a comma-separated list of the object formats + * that are supported on the architecture. + */ +#define OBJFORMAT_NAMES "elf" +#define OBJFORMAT_DEFAULT "elf" + +#define NCPUS 1 + +/* + * Round p (pointer or byte index) up to a correctly-aligned value for all + * data types (int, long, ...). The result is u_long and must be cast to + * any desired pointer type. + * + * ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + * + */ +#define ALIGNBYTES 7 +#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) +#define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0) + +#define PAGE_SIZE 4096 /* bytes/page */ +#define PAGE_SHIFT 12 +#define PAGE_MASK (PAGE_SIZE-1) +#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) + +#define KERNBASE 0xfffffc0000300000LL /* start of kernel virtual */ +#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT) + +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#define DEV_BSIZE (1<<DEV_BSHIFT) + +#ifndef BLKDEV_IOSIZE +#define BLKDEV_IOSIZE PAGE_SIZE /* default block device I/O size */ +#endif +#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */ +#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */ + +#define CLSIZE 1 +#define CLSIZELOG2 0 + +/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */ +#define SSIZE 1 /* initial stack size/NBPG */ +#define SINCR 1 /* increment of stack/NBPG */ + +#define UPAGES 4 /* pages of u-area */ +#define USPACE (UPAGES * PAGE_SIZE) /* total size of u-area */ + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than CLBYTES (the software page size), and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ +#define MSIZE 256 /* size of an mbuf */ +#ifndef MCLSHIFT +# define MCLSHIFT 11 /* convert bytes to m_buf clusters */ + /* 2K cluster can hold Ether frame */ +#endif /* MCLSHIFT */ +#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */ +#define MCLOFSET (MCLBYTES - 1) + +/* + * Size of kernel malloc arena in CLBYTES-sized logical pages + */ +#ifndef NKMEMCLUSTERS +#define NKMEMCLUSTERS (4096*1024/CLBYTES) /* XXX? */ +#endif + +/* pages ("clicks") to disk blocks */ +#define ctod(x) ((x) << (PAGE_SHIFT - DEV_BSHIFT)) +#define dtoc(x) ((x) >> (PAGE_SHIFT - DEV_BSHIFT)) + +/* pages to bytes */ +#define ctob(x) ((x) << PAGE_SHIFT) +#define btoc(x) (((x) + PAGE_MASK) >> PAGE_SHIFT) + +/* bytes to disk blocks */ +#define btodb(x) ((x) >> DEV_BSHIFT) +#define dbtob(x) ((x) << DEV_BSHIFT) + +/* + * Mach derived conversion macros + */ +#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) +#define trunc_page(x) ((unsigned long)(x) & ~(PAGE_MASK)) + +#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) + +#define ia64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define ia64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) + +#define pgtok(x) ((x) * (PAGE_SIZE / 1024)) diff --git a/sys/ia64/include/pcb.h b/sys/ia64/include/pcb.h new file mode 100644 index 0000000..41c3777 --- /dev/null +++ b/sys/ia64/include/pcb.h @@ -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$ + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +/* + * PCB: process control block + */ +struct pcb { + u_int64_t pcb_r4; + u_int64_t pcb_r5; + u_int64_t pcb_r6; + u_int64_t pcb_r7; + + struct ia64_fpreg pcb_f2; + struct ia64_fpreg pcb_f3; + struct ia64_fpreg pcb_f4; + struct ia64_fpreg pcb_f5; + + u_int64_t pcb_old_unat; /* caller's ar.unat */ + u_int64_t pcb_sp; + u_int64_t pcb_pfs; + u_int64_t pcb_bspstore; + + u_int64_t pcb_unat; /* ar.unat for r4..r7 */ + u_int64_t pcb_rnat; + u_int64_t pcb_pr; /* predicates */ + u_int64_t pcb_iip; /* address to restart */ + + unsigned long pcb_onfault; /* for copy faults */ + unsigned long pcb_accessaddr; /* for [fs]uswintr */ +}; + +/* + * The pcb is augmented with machine-dependent additional data for + * core dumps. For the Alpha, that's a trap frame. + */ +struct md_coredump { + struct trapframe md_tf; +}; + +#endif /* _MACHINE_PCB_H_ */ diff --git a/sys/ia64/include/pcpu.h b/sys/ia64/include/pcpu.h new file mode 100644 index 0000000..87c9fe5 --- /dev/null +++ b/sys/ia64/include/pcpu.h @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 1999 Luoqi Chen <luoqi@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_GLOBALDATA_H_ +#define _MACHINE_GLOBALDATA_H_ + +#ifdef _KERNEL + +#include <sys/queue.h> + +/* + * This structure maps out the global data that needs to be kept on a + * per-cpu basis. genassym uses this to generate offsets for the assembler + * code, which also provides external symbols so that C can get at them as + * though they were really globals. This structure is pointed to by + * the per-cpu system value (see alpha_pal_rdval() and alpha_pal_wrval()). + * Inside the kernel, the globally reserved register t7 is used to + * point at the globaldata structure. + */ +struct globaldata { + struct proc *gd_curproc; /* current process */ + struct proc *gd_idleproc; /* idle process */ + struct proc *gd_fpcurproc; /* fp state owner */ + struct pcb *gd_curpcb; /* current pcb */ + struct timeval gd_switchtime; + int gd_switchticks; + u_int gd_cpuno; /* this cpu number */ + u_int gd_other_cpus; /* all other cpus */ + int gd_inside_intr; + u_int64_t gd_idlepcbphys; /* pa of gd_idlepcb */ + u_int64_t gd_pending_ipis; /* pending IPI events */ + u_int32_t gd_next_asn; /* next ASN to allocate */ + u_int32_t gd_current_asngen; /* ASN rollover check */ + u_int32_t gd_intr_nesting_level; /* interrupt recursion */ + + u_int gd_astpending; + SLIST_ENTRY(globaldata) gd_allcpu; +#ifdef KTR_PERCPU + volatile int gd_ktr_idx; /* Index into trace table */ + char *gd_ktr_buf; + char gd_ktr_buf_data[0]; +#endif +}; + +SLIST_HEAD(cpuhead, globaldata); +extern struct cpuhead cpuhead; + +void globaldata_init(struct globaldata *pcpu, int cpuno, size_t sz); +struct globaldata *globaldata_find(int cpuno); + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_GLOBALDATA_H_ */ diff --git a/sys/ia64/include/pmap.h b/sys/ia64/include/pmap.h new file mode 100644 index 0000000..edb7ec5 --- /dev/null +++ b/sys/ia64/include/pmap.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1991 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 William Jolitz of UUNET Technologies 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 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. + * + * Derived from hp300 version by Mike Hibler, this version by William + * Jolitz uses a recursive map [a pde points to the page directory] to + * map the page tables using the pagetables themselves. This is done to + * reduce the impact on kernel virtual memory for lots of sparse address + * space, and to reduce the cost of memory to each process. + * + * from: hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90 + * from: @(#)pmap.h 7.4 (Berkeley) 5/12/91 + * from: i386 pmap.h,v 1.54 1997/11/20 19:30:35 bde Exp + * $FreeBSD$ + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#ifdef LOCORE + +#define PTE_P (1<<0) +#define PTE_MA_WB (0<<2) +#define PTE_MA_UC (4<<2) +#define PTE_MA_UCE (5<<2) +#define PTE_MA_WC (6<<2) +#define PTE_MA_NATPAGE (7<<2) +#define PTE_A (1<<5) +#define PTE_D (1<<6) +#define PTE_PL_KERN (0<<7) +#define PTE_PL_USER (3<<7) +#define PTE_AR_R (0<<9) +#define PTE_AR_RX (1<<9) +#define PTE_AR_RW (2<<9) +#define PTE_AR_RWX (3<<9) +#define PTE_AR_R_RW (4<<9) +#define PTE_AR_RX_RWX (5<<9) +#define PTE_AR_RWX_RW (6<<9) +#define PTE_AR_X_RX (7<<9) + +#else + +#define PTE_MA_WB 0 +#define PTE_MA_UC 4 +#define PTE_MA_UCE 5 +#define PTE_MA_WC 6 +#define PTE_MA_NATPAGE 7 + +#define PTE_PL_KERN 0 +#define PTE_PL_USER 3 + +#define PTE_AR_R 0 +#define PTE_AR_RX 1 +#define PTE_AR_RW 2 +#define PTE_AR_RWX 3 +#define PTE_AR_R_RW 4 +#define PTE_AR_RX_RWX 5 +#define PTE_AR_RWX_RW 6 +#define PTE_AR_X_RX 7 + +#define PTE_IG_WIRED 1 +#define PTE_IG_MANAGED 2 + +/* + * A short-format VHPT entry. Also matches the TLB insertion format. + */ +struct ia64_pte { + u_int64_t pte_p :1; /* bits 0..0 */ + u_int64_t pte_rv1 :1; /* bits 1..1 */ + u_int64_t pte_ma :3; /* bits 2..4 */ + u_int64_t pte_a :1; /* bits 5..5 */ + u_int64_t pte_d :1; /* bits 6..6 */ + u_int64_t pte_pl :2; /* bits 7..8 */ + u_int64_t pte_ar :3; /* bits 9..11 */ + u_int64_t pte_ppn :38; /* bits 12..49 */ + u_int64_t pte_rv2 :2; /* bits 50..51 */ + u_int64_t pte_ed :1; /* bits 52..52 */ + u_int64_t pte_ig :11; /* bits 53..63 */ +}; + +/* + * A long-format VHPT entry. + */ +struct ia64_lpte { + u_int64_t pte_p :1; /* bits 0..0 */ + u_int64_t pte_rv1 :1; /* bits 1..1 */ + u_int64_t pte_ma :3; /* bits 2..4 */ + u_int64_t pte_a :1; /* bits 5..5 */ + u_int64_t pte_d :1; /* bits 6..6 */ + u_int64_t pte_pl :2; /* bits 7..8 */ + u_int64_t pte_ar :3; /* bits 9..11 */ + u_int64_t pte_ppn :38; /* bits 12..49 */ + u_int64_t pte_rv2 :2; /* bits 50..51 */ + u_int64_t pte_ed :1; /* bits 52..52 */ + u_int64_t pte_ig :11; /* bits 53..63 */ + + u_int64_t pte_rv3 :2; /* bits 0..1 */ + u_int64_t pte_ps :6; /* bits 2..7 */ + u_int64_t pte_key :24; /* bits 8..31 */ + u_int64_t pte_rv4 :32; /* bits 32..63 */ + + u_int64_t pte_tag; /* includes ti */ + + u_int64_t pte_chain; /* pa of collision chain */ +}; + +#include <sys/queue.h> + +#ifdef _KERNEL + +/* + * Routine: pmap_kextract + * Function: + * Extract the physical page address associated + * kernel virtual address. + */ +static __inline vm_offset_t +pmap_kextract(vm_offset_t va) +{ + return ia64_tpa(va); +} + +#define vtophys(va) pmap_kextract(((vm_offset_t) (va))) + +#endif /* _KERNEL */ + +/* + * Pmap stuff + */ +struct pv_entry; + +struct md_page { + int pv_list_count; + TAILQ_HEAD(,pv_entry) pv_list; +}; + +struct pmap { + TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ + int pm_count; /* reference count */ + int pm_flags; /* pmap flags */ + int pm_active; /* active flag */ + int pm_asn; /* address space number */ + u_int pm_asngen; /* generation number of pm_asn */ + struct pmap_statistics pm_stats; /* pmap statistics */ + struct vm_page *pm_ptphint; /* pmap ptp hint */ +}; + +#define pmap_resident_count(pmap) (pmap)->pm_stats.resident_count + +#define PM_FLAG_LOCKED 0x1 +#define PM_FLAG_WANTED 0x2 + +typedef struct pmap *pmap_t; + +#ifdef _KERNEL +extern pmap_t kernel_pmap; +#endif + +/* + * For each vm_page_t, there is a list of all currently valid virtual + * mappings of that page. An entry is a pv_entry_t, the list is pv_table. + */ +typedef struct pv_entry { + struct ia64_lpte pv_pte; /* pte for collision walker */ + pmap_t pv_pmap; /* pmap where mapping lies */ + vm_offset_t pv_va; /* virtual address for mapping */ + TAILQ_ENTRY(pv_entry) pv_list; + TAILQ_ENTRY(pv_entry) pv_plist; +} *pv_entry_t; + +#define PV_ENTRY_NULL ((pv_entry_t) 0) + +#ifdef _KERNEL + +extern vm_offset_t avail_end; +extern vm_offset_t avail_start; +extern vm_offset_t clean_eva; +extern vm_offset_t clean_sva; +extern vm_offset_t phys_avail[]; +extern char *ptvmmap; /* poor name! */ +extern vm_offset_t virtual_avail; +extern vm_offset_t virtual_end; + +vm_offset_t pmap_steal_memory __P((vm_size_t)); +void pmap_bootstrap __P((void)); +void pmap_setdevram __P((unsigned long long basea, vm_offset_t sizea)); +int pmap_uses_prom_console __P((void)); +pmap_t pmap_kernel __P((void)); +void *pmap_mapdev __P((vm_offset_t, vm_size_t)); +unsigned *pmap_pte __P((pmap_t, vm_offset_t)) __pure2; +vm_page_t pmap_use_pt __P((pmap_t, vm_offset_t)); +void pmap_set_opt __P((unsigned *)); +void pmap_set_opt_bsp __P((void)); +void pmap_deactivate __P((struct proc *p)); +void pmap_emulate_reference __P((struct proc *p, vm_offset_t v, int user, int write)); + +#endif /* _KERNEL */ + +#endif /* !LOCORE */ + +#endif /* !_MACHINE_PMAP_H_ */ diff --git a/sys/ia64/include/proc.h b/sys/ia64/include/proc.h new file mode 100644 index 0000000..a2e9716 --- /dev/null +++ b/sys/ia64/include/proc.h @@ -0,0 +1,49 @@ +/* $FreeBSD$ */ +/* From: NetBSD: proc.h,v 1.3 1997/04/06 08:47:36 cgd Exp */ + +/* + * Copyright (c) 1994, 1995 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 <machine/globaldata.h> +#include <machine/globals.h> + +/* + * Machine-dependent part of the proc struct for the Alpha. + */ + +struct mdproc { + u_long md_flags; + struct trapframe *md_tf; /* trap/syscall registers */ + struct pcb *md_pcbpaddr; /* phys addr of the pcb */ +}; + +#define MDP_FPUSED 0x0001 /* Process used the FPU */ +#define MDP_UAC_NOPRINT 0x0010 /* Don't print unaligned traps */ +#define MDP_UAC_NOFIX 0x0020 /* Don't fixup unaligned traps */ +#define MDP_UAC_SIGBUS 0x0040 /* Deliver SIGBUS upon + unaligned access */ +#define MDP_UAC_MASK (MDP_UAC_NOPRINT | MDP_UAC_NOFIX | MDP_UAC_SIGBUS) diff --git a/sys/ia64/include/profile.h b/sys/ia64/include/profile.h new file mode 100644 index 0000000..57fbb69 --- /dev/null +++ b/sys/ia64/include/profile.h @@ -0,0 +1,237 @@ +/* $FreeBSD$ */ +/* From: NetBSD: profile.h,v 1.9 1997/04/06 08:47:37 cgd Exp */ + +/* + * 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. + */ + +#define _MCOUNT_DECL void mcount + +#define FUNCTION_ALIGNMENT 32 + +typedef u_long fptrdiff_t; + +#if 0 +/* + * XXX The definition of MCOUNT below is really the following code, run + * XXX through cpp, since the inline assembly isn't preprocessed. + */ +#define OFFSET_AT 0 +#define OFFSET_V0 8 +#define OFFSET_T0 16 +#define OFFSET_T1 24 +#define OFFSET_T2 32 +#define OFFSET_T3 40 +#define OFFSET_T4 48 +#define OFFSET_T5 56 +#define OFFSET_T6 64 +#define OFFSET_T7 72 +#define OFFSET_S6 80 +#define OFFSET_A0 88 +#define OFFSET_A1 96 +#define OFFSET_A2 104 +#define OFFSET_A3 112 +#define OFFSET_A4 120 +#define OFFSET_A5 128 +#define OFFSET_T8 136 +#define OFFSET_T9 144 +#define OFFSET_T10 152 +#define OFFSET_T11 160 +#define OFFSET_RA 168 +#define OFFSET_T12 176 +#define OFFSET_GP 184 +#define FRAME_SIZE 192 + +LEAF(_mcount,0) /* XXX */ + .set noat + .set noreorder + + lda sp, -FRAME_SIZE(sp) + + stq at_reg, OFFSET_AT(sp) + stq v0, OFFSET_V0(sp) + stq t0, OFFSET_T0(sp) + stq t1, OFFSET_T1(sp) + stq t2, OFFSET_T2(sp) + stq t3, OFFSET_T3(sp) + stq t4, OFFSET_T4(sp) + stq t5, OFFSET_T5(sp) + stq t6, OFFSET_T6(sp) + stq t7, OFFSET_T7(sp) + stq s6, OFFSET_S6(sp) /* XXX because run _after_ prologue. */ + stq a0, OFFSET_A0(sp) + stq a1, OFFSET_A1(sp) + stq a2, OFFSET_A2(sp) + stq a3, OFFSET_A3(sp) + stq a4, OFFSET_A4(sp) + stq a5, OFFSET_A5(sp) + stq t8, OFFSET_T8(sp) + stq t9, OFFSET_T9(sp) + stq t10, OFFSET_T10(sp) + stq t11, OFFSET_T11(sp) + stq ra, OFFSET_RA(sp) + stq t12, OFFSET_T12(sp) + stq gp, OFFSET_GP(sp) + + br pv, LX99 +LX99: SETGP(pv) + mov ra, a0 + mov at_reg, a1 + CALL(mcount) + + ldq v0, OFFSET_V0(sp) + ldq t0, OFFSET_T0(sp) + ldq t1, OFFSET_T1(sp) + ldq t2, OFFSET_T2(sp) + ldq t3, OFFSET_T3(sp) + ldq t4, OFFSET_T4(sp) + ldq t5, OFFSET_T5(sp) + ldq t6, OFFSET_T6(sp) + ldq t7, OFFSET_T7(sp) + ldq s6, OFFSET_S6(sp) /* XXX because run _after_ prologue. */ + ldq a0, OFFSET_A0(sp) + ldq a1, OFFSET_A1(sp) + ldq a2, OFFSET_A2(sp) + ldq a3, OFFSET_A3(sp) + ldq a4, OFFSET_A4(sp) + ldq a5, OFFSET_A5(sp) + ldq t8, OFFSET_T8(sp) + ldq t9, OFFSET_T9(sp) + ldq t10, OFFSET_T10(sp) + ldq t11, OFFSET_T11(sp) + ldq ra, OFFSET_RA(sp) + stq t12, OFFSET_T12(sp) + ldq gp, OFFSET_GP(sp) + + ldq at_reg, OFFSET_AT(sp) + + lda sp, FRAME_SIZE(sp) + ret zero, (at_reg), 1 + + END(_mcount) +#endif /* 0 */ + +#define MCOUNT __asm (" \ + .globl _mcount; \ + .ent _mcount 0; \ +_mcount:; \ + .frame $30,0,$26; \ + .set noat; \ + .set noreorder; \ + \ + lda $30, -192($30); \ + \ + stq $28, 0($30); \ + stq $0, 8($30); \ + stq $1, 16($30); \ + stq $2, 24($30); \ + stq $3, 32($30); \ + stq $4, 40($30); \ + stq $5, 48($30); \ + stq $6, 56($30); \ + stq $7, 64($30); \ + stq $8, 72($30); \ + stq $15, 80($30); \ + stq $16, 88($30); \ + stq $17, 96($30); \ + stq $18, 104($30); \ + stq $19, 112($30); \ + stq $20, 120($30); \ + stq $21, 128($30); \ + stq $22, 136($30); \ + stq $23, 144($30); \ + stq $24, 152($30); \ + stq $25, 160($30); \ + stq $26, 168($30); \ + stq $27, 176($30); \ + stq $29, 184($30); \ + \ + br $27, LX98; \ +LX98: ldgp $29,0($27); \ + mov $26, $16; \ + mov $28, $17; \ + jsr $26,mcount; \ + ldgp $29,0($26); \ + \ + ldq $0, 8($30); \ + ldq $1, 16($30); \ + ldq $2, 24($30); \ + ldq $3, 32($30); \ + ldq $4, 40($30); \ + ldq $5, 48($30); \ + ldq $6, 56($30); \ + ldq $7, 64($30); \ + ldq $8, 72($30); \ + ldq $15, 80($30); \ + ldq $16, 88($30); \ + ldq $17, 96($30); \ + ldq $18, 104($30); \ + ldq $19, 112($30); \ + ldq $20, 120($30); \ + ldq $21, 128($30); \ + ldq $22, 136($30); \ + ldq $23, 144($30); \ + ldq $24, 152($30); \ + ldq $25, 160($30); \ + ldq $26, 168($30); \ + ldq $27, 176($30); \ + ldq $29, 184($30); \ + \ + ldq $28, 0($30); \ + \ + lda $30, 192($30); \ + ret $31, ($28), 1; \ + \ + .end _mcount"); + +#ifdef _KERNEL +/* + * The following two macros do splhigh and splx respectively. + * _alpha_pal_swpipl is a special version of alpha_pal_swpipl which + * doesn't include profiling support. + * + * XXX These macros should probably use inline assembly. + */ +#define MCOUNT_ENTER(s) \ + s = _alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH) +#define MCOUNT_EXIT(s) \ + (void)_alpha_pal_swpipl(s); +#define MCOUNT_DECL(s) u_long s; +#ifdef GUPROF +struct gmonparam; + +void nullfunc_loop_profiled __P((void)); +void nullfunc_profiled __P((void)); +void startguprof __P((struct gmonparam *p)); +void stopguprof __P((struct gmonparam *p)); +#else +#define startguprof(p) +#define stopguprof(p) +#endif /* GUPROF */ + +#else /* !_KERNEL */ +typedef u_long uintfptr_t; +#endif diff --git a/sys/ia64/include/ptrace.h b/sys/ia64/include/ptrace.h new file mode 100644 index 0000000..8a7ff84 --- /dev/null +++ b/sys/ia64/include/ptrace.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ptrace.h 8.1 (Berkeley) 6/11/93 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PTRACE_H_ +#define _MACHINE_PTRACE_H_ + +/* + * Machine dependent trace commands. + */ +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) + +#ifdef _KERNEL +int ptrace_read_u_check __P((struct proc *p, vm_offset_t off, size_t len)); +#endif + +#endif + diff --git a/sys/ia64/include/reg.h b/sys/ia64/include/reg.h new file mode 100644 index 0000000..7378e37 --- /dev/null +++ b/sys/ia64/include/reg.h @@ -0,0 +1,58 @@ +/*- + * 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$ + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +struct ia64_fpreg { + u_int64_t fpr_bits[2]; +} __attribute__ ((aligned (16))); + +struct reg { + u_int64_t r_regs[128]; +}; + +struct fpreg { + struct ia64_fpreg fpr_regs[128]; +}; + +struct dbreg { + u_int64_t dbr_data[8]; + u_int64_t dbr_inst[8]; +}; + +#ifdef _KERNEL + +struct proc; + +void restorefpstate __P((struct fpreg *)); +void savefpstate __P((struct fpreg *)); +void setregs __P((struct proc *, u_long, u_long, u_long)); +#endif + +#endif /* _MACHINE_REG_H_ */ diff --git a/sys/ia64/include/reloc.h b/sys/ia64/include/reloc.h new file mode 100644 index 0000000..a8ce0b1 --- /dev/null +++ b/sys/ia64/include/reloc.h @@ -0,0 +1,33 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by John Birrell. + * 4. 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/ia64/include/resource.h b/sys/ia64/include/resource.h new file mode 100644 index 0000000..28fcc98 --- /dev/null +++ b/sys/ia64/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/ia64/include/setjmp.h b/sys/ia64/include/setjmp.h new file mode 100644 index 0000000..5fcfe2a --- /dev/null +++ b/sys/ia64/include/setjmp.h @@ -0,0 +1,46 @@ +/* $FreeBSD$ */ +/* From: NetBSD: setjmp.h,v 1.2 1997/04/06 08:47:41 cgd Exp */ + +/* + * Copyright (c) 1994, 1995 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. + */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 81 /* size, in longs, of a jmp_buf */ + +/* + * 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. + */ +#ifndef _ANSI_SOURCE +typedef struct { long _sjb[_JBLEN + 1]; } sigjmp_buf[1]; +#endif /* not ANSI */ + +typedef struct { long _jb[_JBLEN + 1]; } jmp_buf[1]; diff --git a/sys/ia64/include/sigframe.h b/sys/ia64/include/sigframe.h new file mode 100644 index 0000000..491ce76 --- /dev/null +++ b/sys/ia64/include/sigframe.h @@ -0,0 +1,42 @@ +/*- + * 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 osigframe { +}; + +struct sigframe { + ucontext_t sf_uc; + siginfo_t sf_si; +}; + +#endif /* _MACHINE_SIGFRAME_H_ */ diff --git a/sys/ia64/include/signal.h b/sys/ia64/include/signal.h new file mode 100644 index 0000000..5474941 --- /dev/null +++ b/sys/ia64/include/signal.h @@ -0,0 +1,77 @@ +/* $FreeBSD$ */ +/* From: NetBSD: signal.h,v 1.3 1997/04/06 08:47:43 cgd Exp */ + +/* + * Copyright (c) 1994, 1995 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. + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +typedef long sig_atomic_t; + +#ifndef _ANSI_SOURCE + +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + * + * Note that sc_regs[] and sc_fpregs[]+sc_fpcr are inline + * representations of 'struct reg' and 'struct fpreg', respectively. + */ +typedef unsigned int osigset_t; +struct osigcontext {}; + +/* + * The sequence of the fields should match those in + * mcontext_t. Keep them in sync! + */ +struct sigcontext { + sigset_t sc_mask; /* signal mask to restore */ + unsigned long sc_flags; + unsigned long sc_nat; + unsigned long sc_sp; + unsigned long sc_ip; + unsigned long sc_cfm; + unsigned long sc_um; + unsigned long sc_ar_rsc; + unsigned long sc_ar_bsp; + unsigned long sc_ar_rnat; + unsigned long sc_ar_ccv; + unsigned long sc_ar_unat; + unsigned long sc_ar_fpsr; + unsigned long sc_ar_pfs; + unsigned long sc_pr; + unsigned long sc_br[8]; + unsigned long sc_gr[32]; + struct ia64_fpreg sc_fr[128]; +}; + +#endif /* !_ANSI_SOURCE */ +#endif /* !_MACHINE_SIGNAL_H_*/ diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h new file mode 100644 index 0000000..65c85ef --- /dev/null +++ b/sys/ia64/include/smp.h @@ -0,0 +1,48 @@ +/* + * $FreeBSD$ + */ +#ifndef _MACHINE_SMP_H_ +#define _MACHINE_SMP_H_ + +#ifdef _KERNEL + +#include <machine/mutex.h> +#include <machine/ipl.h> +#include <sys/ktr.h> + +#ifndef LOCORE + +#define BETTER_CLOCK /* unconditional on ia64 */ + +/* global data in mp_machdep.c */ +extern volatile u_int checkstate_probed_cpus; +extern volatile u_int checkstate_need_ast; +extern volatile u_int resched_cpus; +extern void (*cpustop_restartfunc) __P((void)); + +extern int smp_active; +extern int mp_ncpus; +extern u_int all_cpus; +extern u_int started_cpus; +extern u_int stopped_cpus; + +/* functions in mp_machdep.c */ +void mp_start(void); +void mp_announce(void); +void smp_invltlb(void); +void forward_statclock(int pscnt); +void forward_hardclock(int pscnt); +void forward_signal(struct proc *); +void forward_roundrobin(void); +int stop_cpus(u_int); +int restart_cpus(u_int); +void smp_rendezvous_action(void); +void smp_rendezvous(void (*)(void *), + void (*)(void *), + void (*)(void *), + void *arg); +void smp_init_secondary(void); + +#endif /* !LOCORE */ +#endif /* _KERNEL */ +#endif diff --git a/sys/ia64/include/stdarg.h b/sys/ia64/include/stdarg.h new file mode 100644 index 0000000..e8dde78 --- /dev/null +++ b/sys/ia64/include/stdarg.h @@ -0,0 +1,50 @@ +/* $FreeBSD$ */ +/* From: NetBSD: stdarg.h,v 1.7 1997/04/06 08:47:44 cgd Exp */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_STDARG_H_ +#define _MACHINE_STDARG_H_ + +#include <machine/ansi.h> + +typedef _BSD_VA_LIST_ va_list; + +#define va_start(list, parmN) __builtin_stdarg_start(&(list), parmN) +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg + +#endif /* !_MACHINE_STDARG_H_ */ diff --git a/sys/ia64/include/sysarch.h b/sys/ia64/include/sysarch.h new file mode 100644 index 0000000..b990bcd --- /dev/null +++ b/sys/ia64/include/sysarch.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Architecture specific syscalls (alpha) + */ +#ifndef _MACHINE_SYSARCH_H_ +#define _MACHINE_SYSARCH_H_ + +#ifndef _KERNEL +#include <sys/cdefs.h> + +__BEGIN_DECLS +__END_DECLS +#endif + +#endif /* !_MACHINE_SYSARCH_H_ */ diff --git a/sys/ia64/include/types.h b/sys/ia64/include/types.h new file mode 100644 index 0000000..ccb7793 --- /dev/null +++ b/sys/ia64/include/types.h @@ -0,0 +1,73 @@ +/* $FreeBSD$ */ +/* From: NetBSD: types.h,v 1.8 1997/04/06 08:47:45 cgd Exp */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + */ + +#ifndef _MACHTYPES_H_ +#define _MACHTYPES_H_ + +#include <sys/cdefs.h> + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +typedef struct _physadr { + long r[1]; +} *physadr; + +typedef struct label_t { + long val[10]; +} label_t; +#endif + +typedef unsigned long vm_offset_t; +typedef long vm_ooffset_t; +typedef unsigned long vm_pindex_t; +typedef unsigned long vm_size_t; + + +typedef __int64_t register_t; + +#ifdef _KERNEL +typedef long intfptr_t; +typedef unsigned long uintfptr_t; +#endif + +/* Interrupt mask (spl, xxx_imask, etc) */ +typedef __uint32_t intrmask_t; + +/* Interrupt handler function type */ +typedef void inthand2_t(void *); + +#endif /* _MACHTYPES_H_ */ diff --git a/sys/ia64/include/ucontext.h b/sys/ia64/include/ucontext.h new file mode 100644 index 0000000..bb18d76 --- /dev/null +++ b/sys/ia64/include/ucontext.h @@ -0,0 +1,67 @@ +/*- + * 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_UCONTEXT_H_ +#define _MACHINE_UCONTEXT_H_ + +#define IA64_MC_FLAG_ONSTACK 0 +#define IA64_MC_FLAG_IN_SYSCALL 1 +#define IA64_MC_FLAG_FPH_VALID 2 + +typedef struct __mcontext { + /* + * These fields must match the definition + * of struct sigcontext. That way we can support + * struct sigcontext and ucontext_t at the same + * time. + * + * We use the same layout as Linux/ia64 to make emulation + * easier. + */ + unsigned long mc_flags; + unsigned long mc_nat; + unsigned long mc_sp; + unsigned long mc_ip; + unsigned long mc_cfm; + unsigned long mc_um; + unsigned long mc_ar_rsc; + unsigned long mc_ar_bsp; + unsigned long mc_ar_rnat; + unsigned long mc_ar_ccv; + unsigned long mc_ar_unat; + unsigned long mc_ar_fpsr; + unsigned long mc_ar_pfs; + unsigned long mc_pr; + unsigned long mc_br[8]; + unsigned long mc_gr[32]; + struct ia64_fpreg mc_fr[128]; +} mcontext_t; + +#endif /* !_MACHINE_UCONTEXT_H_ */ diff --git a/sys/ia64/include/varargs.h b/sys/ia64/include/varargs.h new file mode 100644 index 0000000..25b156b --- /dev/null +++ b/sys/ia64/include/varargs.h @@ -0,0 +1,57 @@ +/* $FreeBSD$ */ +/* From: NetBSD: varargs.h,v 1.7 1997/04/06 08:47:46 cgd Exp */ + +/*- + * Copyright (c) 1990, 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. + * 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. + * + * @(#)varargs.h 8.2 (Berkeley) 3/22/94 + */ + +#ifndef _MACHINE_VARARGS_H_ +#define _MACHINE_VARARGS_H_ + +#include <machine/stdarg.h> + +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; ... + +#undef va_start +#define va_start(ap) __builtin_varargs_start(&(ap)) + +#endif /* !_MACHINE_VARARGS_H_ */ diff --git a/sys/ia64/include/vmparam.h b/sys/ia64/include/vmparam.h new file mode 100644 index 0000000..2cdc959 --- /dev/null +++ b/sys/ia64/include/vmparam.h @@ -0,0 +1,161 @@ +/* $FreeBSD$ */ +/* From: NetBSD: vmparam.h,v 1.6 1997/09/23 23:23:23 mjacob Exp */ +#ifndef _ALPHA_VMPARAM_H +#define _ALPHA_VMPARAM_H +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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: Utah $Hdr: vmparam.h 1.16 91/01/18$ + * + * @(#)vmparam.h 8.2 (Berkeley) 4/22/94 + */ + +/* + * Machine dependent constants for Alpha. + */ +/* + * USRTEXT is the start of the user text/data space, while USRSTACK + * is the top (end) of the user stack. Immediately above the user stack + * resides the user structure, which is UPAGES long and contains the + * kernel stack. + */ +#define USRTEXT CLBYTES +/* #define USRSTACK VM_MAXUSER_ADDRESS */ + +/* + * This stack location is suitable for OSF1 emulation. Some OSF + * programs are built as 32bit and assume that the stack is reachable + * with a 32bit value. OSF1 manages to have a variable location for + * the user stack which we should probably also support. + */ +#define USRSTACK (0x12000000LL - (UPAGES*PAGE_SIZE)) + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ (1<<30) /* max text size (1G) */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (1<<27) /* initial data size (128M) */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (1<<30) /* max data size (1G) */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (1<<21) /* initial stack size (2M) */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (1<<25) /* max stack size (32M) */ +#endif +#ifndef SGROWSIZ +#define SGROWSIZ (128UL*1024) /* amount to grow stack */ +#endif + +/* + * PTEs for mapping user space into the kernel for phyio operations. + * 64 pte's are enough to cover 8 disks * MAXBSIZE. + */ +#ifndef USRIOSIZE +#define USRIOSIZE 64 +#endif + +/* + * Boundary at which to place first MAPMEM segment if not explicitly + * specified. Should be a power of two. This allows some slop for + * the data segment to grow underneath the first mapped segment. + */ +#define MMSEG 0x200000 + +/* + * The size of the clock loop. + */ +#define LOOPPAGES (maxfree - firstfree) + +/* + * 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 + +/* + * A swapped in process is given a small amount of core without being bothered + * by the page replacement algorithm. Basically this says that if you are + * swapped in you deserve some resources. We protect the last SAFERSS + * pages against paging and will just swap you out rather than paging you. + * Note that each process has at least UPAGES+CLSIZE pages which are not + * paged anyways, in addition to SAFERSS. + */ +#define SAFERSS 10 /* nominal ``small'' resident set size + protected against replacement */ + +/* + * Mach derived constants + */ + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS 0 +#define VM_MAXUSER_ADDRESS IA64_RR_BASE(5) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MIN_KERNEL_ADDRESS IA64_RR_BASE(5) +#define VM_MAX_KERNEL_ADDRESS (IA64_RR_BASE(6) - 1) + +/* virtual sizes (bytes) for various kernel submaps */ +#ifndef VM_KMEM_SIZE +#define VM_KMEM_SIZE (12 * 1024 * 1024) +#endif + +/* + * How many physical pages per KVA page allocated. + * min(max(VM_KMEM_SIZE, Physical memory/VM_KMEM_SIZE_SCALE), VM_KMEM_SIZE_MAX) + * is the total KVA space allocated for kmem_map. + */ +#ifndef VM_KMEM_SIZE_SCALE +#define VM_KMEM_SIZE_SCALE (4) /* XXX 8192 byte pages */ +#endif + +/* initial pagein size of beginning of executable file */ +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 +#endif + +#endif /* !_ALPHA_VMPARAM_H */ diff --git a/sys/ia64/isa/isa.c b/sys/ia64/isa/isa.c new file mode 100644 index 0000000..8ac1516 --- /dev/null +++ b/sys/ia64/isa/isa.c @@ -0,0 +1,171 @@ +/*- + * 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$ + */ + +/* + * Modifications for Intel architecture by Garrett A. Wollman. + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/resource.h> + +#include <isa/isareg.h> +#include <isa/isavar.h> +#include <isa/isa_common.h> + +void +isa_init(void) +{ +} + +intrmask_t +isa_irq_pending(void) +{ + u_char irr1; + u_char irr2; + + irr1 = inb(IO_ICU1); + irr2 = inb(IO_ICU2); + return ((irr2 << 8) | irr1); +} + +/* + * This implementation simply passes the request up to the parent + * bus, which in our case is the special i386 nexus, substituting any + * configured values if the caller defaulted. We can get away with + * this because there is no special mapping for ISA resources on an Intel + * platform. When porting this code to another architecture, it may be + * necessary to interpose a mapping layer here. + */ +struct resource * +isa_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + /* + * Consider adding a resource definition. We allow rid 0-1 for + * irq and drq, 0-3 for memory and 0-7 for ports which is + * sufficient for isapnp. + */ + int passthrough = (device_get_parent(child) != bus); + int isdefault = (start == 0UL && end == ~0UL); + struct isa_device* idev = DEVTOISA(child); + struct resource_list *rl = &idev->id_resources; + struct resource_list_entry *rle; + + if (!passthrough && !isdefault) { + rle = resource_list_find(rl, type, *rid); + if (!rle) { + if (*rid < 0) + return 0; + switch (type) { + case SYS_RES_IRQ: + if (*rid >= ISA_NIRQ) + return 0; + break; + case SYS_RES_DRQ: + if (*rid >= ISA_NDRQ) + return 0; + break; + case SYS_RES_MEMORY: + if (*rid >= ISA_NMEM) + return 0; + break; + case SYS_RES_IOPORT: + if (*rid >= ISA_NPORT) + return 0; + break; + default: + return 0; + } + resource_list_add(rl, type, *rid, start, end, count); + } + } + + return resource_list_alloc(rl, bus, child, type, rid, + start, end, count, flags); +} + +int +isa_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + struct isa_device* idev = DEVTOISA(child); + struct resource_list *rl = &idev->id_resources; + return resource_list_release(rl, bus, child, type, rid, r); +} + +/* + * We can't use the bus_generic_* versions of these methods because those + * methods always pass the bus param as the requesting device, and we need + * to pass the child (the i386 nexus knows about this and is prepared to + * deal). + */ +int +isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags, + void (*ihand)(void *), void *arg, void **cookiep) +{ + return (BUS_SETUP_INTR(device_get_parent(bus), child, r, flags, + ihand, arg, cookiep)); +} + +int +isa_teardown_intr(device_t bus, device_t child, struct resource *r, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, cookie)); +} diff --git a/sys/ia64/isa/isa_dma.c b/sys/ia64/isa/isa_dma.c new file mode 100644 index 0000000..1eb95c9 --- /dev/null +++ b/sys/ia64/isa/isa_dma.c @@ -0,0 +1,512 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 + * from: isa_dma.c,v 1.3 1999/05/09 23:56:00 peter Exp $ + * $FreeBSD$ + */ + +/* + * code to manage AT bus + * + * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): + * Fixed uninitialized variable problem and added code to deal + * with DMA page boundaries in isa_dmarangecheck(). Fixed word + * mode DMA count compution and reorganized DMA setup code in + * isa_dmastart() + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/bus.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <isa/isareg.h> +#include <isa/isavar.h> +#include <i386/isa/ic/i8237.h> +#include <machine/bus.h> + +/* +** Register definitions for DMA controller 1 (channels 0..3): +*/ +#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ +#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ +#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ +#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ +#define DMA1_RESET (IO_DMA1 + 1*13) /* reset */ + +/* +** Register definitions for DMA controller 2 (channels 4..7): +*/ +#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ +#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ +#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ +#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ +#define DMA2_RESET (IO_DMA2 + 2*13) /* reset */ + +static bus_dma_tag_t dma_tag[8]; +static bus_dmamap_t dma_map[8]; +static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ +static u_int8_t dma_inuse = 0; /* User for acquire/release */ +static u_int8_t dma_auto_mode = 0; +static u_int8_t dma_bounced = 0; + +#define VALID_DMA_MASK (7) + +/* high byte of address is stored in this port for i-th dma channel */ +static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; + +/* + * Setup a DMA channel's bounce buffer. + */ +void +isa_dmainit(chan, bouncebufsize) + int chan; + u_int bouncebufsize; +{ + static int initted = 0; + bus_addr_t boundary = chan >= 4 ? 0x20000 : 0x10000; + + if (!initted) { + /* + * Reset the DMA hardware. + */ + outb(DMA1_RESET, 0); + outb(DMA2_RESET, 0); + isa_dmacascade(4); + + initted = 1; + } + +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmainit: channel out of range"); + + if (dma_tag[chan] || dma_map[chan]) + panic("isa_dmainit: impossible request"); +#endif + + if (bus_dma_tag_create(/*parent*/NULL, + /*alignment*/2, + /*boundary*/boundary, + /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, + /*highaddr*/BUS_SPACE_MAXADDR, + /*filter*/NULL, /*filterarg*/NULL, + /*maxsize*/bouncebufsize, + /*nsegments*/1, /*maxsegz*/0x3ffff, + /*flags*/BUS_DMA_ISA, + &dma_tag[chan]) != 0) { + panic("isa_dmainit: unable to create dma tag\n"); + } + + if (bus_dmamap_create(dma_tag[chan], 0, &dma_map[chan])) { + panic("isa_dmainit: unable to create dma map\n"); + } + +} + +/* + * Register a DMA channel's usage. Usually called from a device driver + * in open() or during its initialization. + */ +int +isa_dma_acquire(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dma_acquire: channel out of range"); +#endif + + if (dma_inuse & (1 << chan)) { + printf("isa_dma_acquire: channel %d already in use\n", chan); + return (EBUSY); + } + dma_inuse |= (1 << chan); + dma_auto_mode &= ~(1 << chan); + + return (0); +} + +/* + * Unregister a DMA channel's usage. Usually called from a device driver + * during close() or during its shutdown. + */ +void +isa_dma_release(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dma_release: channel out of range"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dma_release: channel %d not in use\n", chan); +#endif + + if (dma_busy & (1 << chan)) { + dma_busy &= ~(1 << chan); + /* + * XXX We should also do "dma_bounced &= (1 << chan);" + * because we are acting on behalf of isa_dmadone() which + * was not called to end the last DMA operation. This does + * not matter now, but it may in the future. + */ + } + + dma_inuse &= ~(1 << chan); + dma_auto_mode &= ~(1 << chan); +} + +/* + * isa_dmacascade(): program 8237 DMA controller channel to accept + * external dma control by a board. + */ +void +isa_dmacascade(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmacascade: channel out of range"); +#endif + + /* set dma channel mode, and set dma channel mode */ + if ((chan & 4) == 0) { + outb(DMA1_MODE, DMA37MD_CASCADE | chan); + outb(DMA1_SMSK, chan); + } else { + outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); + outb(DMA2_SMSK, chan & 3); + } +} + +/* + * isa_dmastart(): program 8237 DMA controller channel. + */ + +struct isa_dmastart_arg { + caddr_t addr; + int chan; + int flags; +}; + +static void isa_dmastart_cb(void *arg, bus_dma_segment_t *segs, int nseg, + int error) +{ + caddr_t addr = ((struct isa_dmastart_arg *) arg)->addr; + int chan = ((struct isa_dmastart_arg *) arg)->chan; + int flags = ((struct isa_dmastart_arg *) arg)->flags; + bus_addr_t phys = segs->ds_addr; + int nbytes = segs->ds_len; + int waport; + + if (nseg != 1) + panic("isa_dmastart: transfer mapping not contiguous"); + +#if 0 + if ((chipset.sgmap == NULL) && + (pmap_extract(pmap_kernel(), (vm_offset_t)addr) + > BUS_SPACE_MAXADDR_24BIT)) { + /* we bounced */ + dma_bounced |= (1 << chan); + /* copy bounce buffer on write */ + if (!(flags & ISADMA_READ)) + bus_dmamap_sync(dma_tag[chan], dma_map[chan], + BUS_DMASYNC_PREWRITE); + } +#endif + + if ((chan & 4) == 0) { + /* + * Program one of DMA channels 0..3. These are + * byte mode channels. + */ + /* set dma channel mode, and reset address ff */ + + /* If ISADMA_RAW flag is set, then use autoinitialise mode */ + if (flags & ISADMA_RAW) { + if (flags & ISADMA_READ) + outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); + else + outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); + } + else + if (flags & ISADMA_READ) + outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); + else + outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); + outb(DMA1_FFC, 0); + + /* send start address */ + waport = DMA1_CHN(chan); + outb(waport, phys); + outb(waport, phys>>8); + outb(dmapageport[chan], phys>>16); + + /* send count */ + outb(waport + 1, --nbytes); + outb(waport + 1, nbytes>>8); + + /* unmask channel */ + outb(DMA1_SMSK, chan); + } else { + /* + * Program one of DMA channels 4..7. These are + * word mode channels. + */ + /* set dma channel mode, and reset address ff */ + + /* If ISADMA_RAW flag is set, then use autoinitialise mode */ + if (flags & ISADMA_RAW) { + if (flags & ISADMA_READ) + outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); + else + outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); + } + else + if (flags & ISADMA_READ) + outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); + else + outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); + outb(DMA2_FFC, 0); + + /* send start address */ + waport = DMA2_CHN(chan - 4); + outb(waport, phys>>1); + outb(waport, phys>>9); + outb(dmapageport[chan], phys>>16); + + /* send count */ + nbytes >>= 1; + outb(waport + 2, --nbytes); + outb(waport + 2, nbytes>>8); + + /* unmask channel */ + outb(DMA2_SMSK, chan & 3); + } +} + +void +isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) +{ + struct isa_dmastart_arg args; + +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmastart: channel out of range"); + + if ((chan < 4 && nbytes > (1<<16)) + || (chan >= 4 && (nbytes > (1<<17) || (uintptr_t)addr & 1))) + panic("isa_dmastart: impossible request"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastart: channel %d not acquired\n", chan); +#endif + +#if 0 + /* + * XXX This should be checked, but drivers like ad1848 only call + * isa_dmastart() once because they use Auto DMA mode. If we + * leave this in, drivers that do this will print this continuously. + */ + if (dma_busy & (1 << chan)) + printf("isa_dmastart: channel %d busy\n", chan); +#endif + + if (!dma_tag || !dma_map[chan]) + panic("isa_dmastart: called without isa_dmainit"); + + dma_busy |= (1 << chan); + + if (flags & ISADMA_RAW) { + dma_auto_mode |= (1 << chan); + } else { + dma_auto_mode &= ~(1 << chan); + } + + /* + * Freeze dma while updating registers. + */ + outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); + + args.addr = addr; + args.chan = chan; + args.flags = flags; + bus_dmamap_load(dma_tag[chan], dma_map[chan], addr, nbytes, + isa_dmastart_cb, &args, 0); +} + +void +isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmadone: channel out of range"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmadone: channel %d not acquired\n", chan); +#endif + + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) + printf("isa_dmadone: channel %d not busy\n", chan); + + if (dma_bounced & (1 << chan)) { + /* copy bounce buffer on read */ + if (flags & ISADMA_READ) { + bus_dmamap_sync(dma_tag[chan], dma_map[chan], + BUS_DMASYNC_POSTREAD); + } + dma_bounced &= ~(1 << chan); + } + + if ((dma_auto_mode & (1 << chan)) == 0) { + outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); + bus_dmamap_unload(dma_tag[chan], dma_map[chan]); + } + + dma_busy &= ~(1 << chan); +} + +/* + * Query the progress of a transfer on a DMA channel. + * + * To avoid having to interrupt a transfer in progress, we sample + * each of the high and low databytes twice, and apply the following + * logic to determine the correct count. + * + * Reads are performed with interrupts disabled, thus it is to be + * expected that the time between reads is very small. At most + * one rollover in the low count byte can be expected within the + * four reads that are performed. + * + * There are three gaps in which a rollover can occur : + * + * - read low1 + * gap1 + * - read high1 + * gap2 + * - read low2 + * gap3 + * - read high2 + * + * If a rollover occurs in gap1 or gap2, the low2 value will be + * greater than the low1 value. In this case, low2 and high2 are a + * corresponding pair. + * + * In any other case, low1 and high1 can be considered to be correct. + * + * The function returns the number of bytes remaining in the transfer, + * or -1 if the channel requested is not active. + * + */ +int +isa_dmastatus(int chan) +{ + u_long cnt = 0; + int ffport, waport; + u_long low1, high1, low2, high2; + int s; + + /* channel active? */ + if ((dma_inuse & (1 << chan)) == 0) { + printf("isa_dmastatus: channel %d not active\n", chan); + return(-1); + } + /* channel busy? */ + + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) { + printf("chan %d not busy\n", chan); + return -2 ; + } + if (chan < 4) { /* low DMA controller */ + ffport = DMA1_FFC; + waport = DMA1_CHN(chan) + 1; + } else { /* high DMA controller */ + ffport = DMA2_FFC; + waport = DMA2_CHN(chan - 4) + 2; + } + + s = splhigh(); /* no interrupts Mr Jones! */ + outb(ffport, 0); /* clear register LSB flipflop */ + low1 = inb(waport); + high1 = inb(waport); + outb(ffport, 0); /* clear again */ + low2 = inb(waport); + high2 = inb(waport); + splx(s); /* enable interrupts again */ + + /* + * Now decide if a wrap has tried to skew our results. + * Note that after TC, the count will read 0xffff, while we want + * to return zero, so we add and then mask to compensate. + */ + if (low1 >= low2) { + cnt = (low1 + (high1 << 8) + 1) & 0xffff; + } else { + cnt = (low2 + (high2 << 8) + 1) & 0xffff; + } + + if (chan >= 4) /* high channels move words */ + cnt *= 2; + return(cnt); +} + +/* + * Stop a DMA transfer currently in progress. + */ +int +isa_dmastop(int chan) +{ + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastop: channel %d not acquired\n", chan); + + if (((dma_busy & (1 << chan)) == 0) && + ((dma_auto_mode & (1 << chan)) == 0)) { + printf("chan %d not busy\n", chan); + return -2 ; + } + + if ((chan & 4) == 0) { + outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); + } else { + outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); + } + return(isa_dmastatus(chan)); +} |