code:
/*	$OpenBSD: pmap.c,v 1.27 2015/02/11 03:24:47 miod Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef SMALL_KERNEL
#define	PMAPDEBUG
#endif

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/pool.h>
#include <sys/extent.h>

#include <uvm/uvm.h>

#include <machine/iomod.h>

#include <dev/rndvar.h>

#ifdef PMAPDEBUG
#define	DPRINTF(l,s)	do {		\
	if ((pmapdebug & (l)) == (l))	\
		printf s;		\
} while(0)
#define	PDB_FOLLOW	0x00000001
#define	PDB_INIT	0x00000002
#define	PDB_ENTER	0x00000004
#define	PDB_REMOVE	0x00000008
#define	PDB_CREATE	0x00000010
#define	PDB_PTPAGE	0x00000020
#define	PDB_CACHE	0x00000040
#define	PDB_BITS	0x00000080
#define	PDB_COLLECT	0x00000100
#define	PDB_PROTECT	0x00000200
#define	PDB_EXTRACT	0x00000400
#define	PDB_VP		0x00000800
#define	PDB_PV		0x00001000
#define	PDB_PARANOIA	0x00002000
#define	PDB_WIRING	0x00004000
#define	PDB_PMAP	0x00008000
#define	PDB_STEAL	0x00010000
#define	PDB_PHYS	0x00020000
#define	PDB_POOL	0x00040000
int pmapdebug = 0
	| PDB_INIT
/*	| PDB_FOLLOW */
/*	| PDB_VP */
/*	| PDB_PV */
/*	| PDB_ENTER */
/*	| PDB_REMOVE */
/*	| PDB_STEAL */
/*	| PDB_PROTECT */
/*	| PDB_PHYS */
	;
#else
#define	DPRINTF(l,s)	/* */
#endif

paddr_t physical_steal, physical_end;

struct pmap	kernel_pmap_store;
struct pool	pmap_pmap_pool;
struct pool	pmap_pv_pool;
int		pmap_pvlowat = 252;
int 		pmap_initialized;
int		pmap_nkpdes = 32;

pt_entry_t	hppa_prot[8];
#define	pmap_prot(m,vp) (hppa_prot[(vp)] | ((m) == pmap_kernel()? 0 : PTE_USER))

pt_entry_t	kernel_ptes[] = {
	PTE_EXEC  | PTE_ORDER | PTE_PREDICT | PTE_WIRED |
	    TLB_PAGE(0x000000) | PTE_PG4M,
	PTE_WRITE | PTE_ORDER | PTE_DIRTY   | PTE_WIRED |
	    TLB_PAGE(0x400000) | PTE_PG4M,
	PTE_WRITE | PTE_ORDER | PTE_DIRTY   | PTE_WIRED |
	    TLB_PAGE(0x800000) | PTE_PG4M,
	PTE_WRITE | PTE_ORDER | PTE_DIRTY   | PTE_WIRED |
	    TLB_PAGE(0xc00000) | PTE_PG4M
};

#define	pmap_pvh_attrs(a) \
	(((a) & PTE_DIRTY) | ((a) ^ PTE_REFTRAP))

struct vm_page	*pmap_pagealloc(struct uvm_object *obj, voff_t off);
volatile pt_entry_t *pmap_pde_get(volatile u_int32_t *pd, vaddr_t va);
void		 pmap_pde_set(struct pmap *pm, vaddr_t va, paddr_t ptp);
void		 pmap_pte_flush(struct pmap *pmap, vaddr_t va, pt_entry_t pte);
pt_entry_t *	 pmap_pde_alloc(struct pmap *pm, vaddr_t va,
		    struct vm_page **pdep);
#ifdef DDB
void		 pmap_dump_table(pa_space_t space, vaddr_t sva);
void		 pmap_dump_pv(paddr_t pa);
#endif
int		 pmap_check_alias(struct pv_entry *pve, vaddr_t va,
		    pt_entry_t pte);
void		 pmap_pv_free(struct pv_entry *pv);
void		 pmap_pv_enter(struct vm_page *pg, struct pv_entry *pve,
		    struct pmap *pm, vaddr_t va, struct vm_page *pdep);
struct pv_entry *pmap_pv_remove(struct vm_page *pg, struct pmap *pmap,
		    vaddr_t va);
void		 pmap_maphys(paddr_t spa, paddr_t epa);

#define	IS_IOPAGE(pa)	((pa) >= (HPPA_IOBEGIN & HPPA_PHYSMAP))

struct vm_page *
pmap_pagealloc(struct uvm_object *obj, voff_t off)
{
	struct vm_page *pg;

	if ((pg = uvm_pagealloc(obj, off, NULL,
	    UVM_PGA_USERESERVE | UVM_PGA_ZERO)) == NULL)
		printf("pmap_pagealloc fail\n");

	return (pg);
}

volatile pt_entry_t *
pmap_pde_get(volatile u_int32_t *pd, vaddr_t va)
{
	int i;

	DPRINTF(PDB_FOLLOW|PDB_VP,
	    ("pmap_pde_get(%p, 0x%lx)\n", pd, va));

	i = (va & PIE_MASK) >> PIE_SHIFT;
	if (i) {
		pd = (volatile u_int32_t *)((u_int64_t)pd[i] << PAGE_SHIFT);

		if (!pd)
			return (NULL);
	} else
		pd += PAGE_SIZE / sizeof(*pd);

	i = (va & PDE_MASK) >> PDE_SHIFT;
	return (pt_entry_t *)((u_int64_t)pd[i] << PAGE_SHIFT);
}

void
pmap_pde_set(struct pmap *pm, vaddr_t va, paddr_t ptp)
{
	volatile u_int32_t *pd = pm->pm_pdir;
	int i;

	DPRINTF(PDB_FOLLOW|PDB_VP,
	    ("pmap_pde_set(%p, 0x%lx, 0x%lx)\n", pm, va, ptp));

	i = (va & PIE_MASK) >> PIE_SHIFT;
	if (i)
		pd = (volatile u_int32_t *)((u_int64_t)pd[i] << PAGE_SHIFT);
	else
		pd += PAGE_SIZE / sizeof(*pd);

	i = (va & PDE_MASK) >> PDE_SHIFT;
	pd[i] = ptp >> PAGE_SHIFT;
}

pt_entry_t *
pmap_pde_alloc(struct pmap *pm, vaddr_t va, struct vm_page **pdep)
{
	struct vm_page *pg;
	paddr_t pa;

	DPRINTF(PDB_FOLLOW|PDB_VP,
	    ("pmap_pde_alloc(%p, 0x%lx, %p)\n", pm, va, pdep));

	if ((pg = pmap_pagealloc(&pm->pm_obj, va)) == NULL)
		return (NULL);

	pa = VM_PAGE_TO_PHYS(pg);

	DPRINTF(PDB_FOLLOW|PDB_VP, ("pmap_pde_alloc: pde %lx\n", pa));

	atomic_clearbits_int(&pg->pg_flags, PG_BUSY);
	pg->wire_count = 1;		/* no mappings yet */
	pmap_pde_set(pm, va, pa);
	pm->pm_stats.resident_count++;	/* count PTP as resident */
	pm->pm_ptphint = pg;
	if (pdep)
		*pdep = pg;
	return ((pt_entry_t *)pa);
}

static __inline struct vm_page *
pmap_pde_ptp(struct pmap *pm, volatile pt_entry_t *pde)
{
	paddr_t pa = (paddr_t)pde;

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp(%p, %p)\n", pm, pde));

	if (pm->pm_ptphint && VM_PAGE_TO_PHYS(pm->pm_ptphint) == pa)
		return (pm->pm_ptphint);

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp: lookup 0x%lx\n", pa));

	return (PHYS_TO_VM_PAGE(pa));
}

static __inline void
pmap_pde_release(struct pmap *pmap, vaddr_t va, struct vm_page *ptp)
{
	paddr_t pa;

	DPRINTF(PDB_FOLLOW|PDB_PV,
	    ("pmap_pde_release(%p, 0x%lx, %p)\n", pmap, va, ptp));

	if (pmap != pmap_kernel() && --ptp->wire_count <= 1) {
		DPRINTF(PDB_FOLLOW|PDB_PV,
		    ("pmap_pde_release: disposing ptp %p\n", ptp));

		pmap_pde_set(pmap, va, 0);
		pmap->pm_stats.resident_count--;
		if (pmap->pm_ptphint == ptp)
			pmap->pm_ptphint = RB_ROOT(&pmap->pm_obj.memt);
		ptp->wire_count = 0;
#ifdef DIAGNOSTIC
		if (ptp->pg_flags & PG_BUSY)
			panic("pmap_pde_release: busy page table page");
#endif
		pa = VM_PAGE_TO_PHYS(ptp);
		pdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
		pdtlb(HPPA_SID_KERNEL, pa);
		uvm_pagefree(ptp);
	}
}

static __inline pt_entry_t
pmap_pte_get(volatile pt_entry_t *pde, vaddr_t va)
{
	DPRINTF(PDB_FOLLOW|PDB_VP,
	    ("pmap_pte_get(%p, 0x%lx)\n", pde, va));

	return (pde[(va & PTE_MASK) >> PTE_SHIFT]);
}

static __inline void
pmap_pte_set(volatile pt_entry_t *pde, vaddr_t va, pt_entry_t pte)
{
	DPRINTF(PDB_FOLLOW|PDB_VP,
	    ("pmap_pte_set(%p, 0x%lx, 0x%lx)\n", pde, va, (long)pte));

	pde[(va & PTE_MASK) >> PTE_SHIFT] = pte;
}

void
pmap_pte_flush(struct pmap *pmap, vaddr_t va, pt_entry_t pte)
{
	fdcache(pmap->pm_space, va, PAGE_SIZE);
	if (pte & PTE_EXEC) {
		ficache(pmap->pm_space, va, PAGE_SIZE);
		pdtlb(pmap->pm_space, va);
		pitlb(pmap->pm_space, va);
	} else
		pdtlb(pmap->pm_space, va);
}

static __inline pt_entry_t
pmap_vp_find(struct pmap *pm, vaddr_t va)
{
	volatile pt_entry_t *pde;

	if (!(pde = pmap_pde_get(pm->pm_pdir, va)))
		return (0);

	return (pmap_pte_get(pde, va));
}

#ifdef DDB
void
pmap_dump_table(pa_space_t space, vaddr_t sva)
{
	volatile pt_entry_t *pde;
	volatile u_int32_t *pd;
	pt_entry_t pte;
	vaddr_t va, pdemask;

	if (space)
		pd = (u_int32_t *)mfctl(CR_VTOP);
	else
		pd = pmap_kernel()->pm_pdir;

	for (pdemask = 1, va = sva ? sva : 0;
	    va < VM_MAX_ADDRESS; va += PAGE_SIZE) {
		if (pdemask != (va & (PDE_MASK|PIE_MASK))) {
			pdemask = va & (PDE_MASK|PIE_MASK);
			if (!(pde = pmap_pde_get(pd, va))) {
				va = pdemask + PTE_MASK;
				continue;
			}
			printf("%x:%8p:\n", space, pde);
		}

		if (!(pte = pmap_pte_get(pde, va)))
			continue;

		printf("0x%08lx-0x%08llx:%lb\n",
		    va, PTE_PAGE(pte), (long)PTE_GETBITS(pte), PTE_BITS);
	}
}

void
pmap_dump_pv(paddr_t pa)
{
	struct vm_page *pg;
	struct pv_entry *pve;

	pg = PHYS_TO_VM_PAGE(pa);
	for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next)
		printf("%x:%lx\n", pve->pv_pmap->pm_space, pve->pv_va);
}
#endif

int
pmap_check_alias(struct pv_entry *pve, vaddr_t va, pt_entry_t pte)
{
	int ret;

	/* check for non-equ aliased mappings */
	for (ret = 0; pve; pve = pve->pv_next) {
		pte |= pmap_vp_find(pve->pv_pmap, pve->pv_va);
		if ((va & HPPA_PGAOFF) != (pve->pv_va & HPPA_PGAOFF) &&
		    (pte & PTE_WRITE)) {
#ifdef PMAPDEBUG
			printf("pmap_check_alias: "
			    "aliased writable mapping 0x%x:0x%lx\n",
			    pve->pv_pmap->pm_space, pve->pv_va);
			ret++;
#endif
		}
	}

	return (ret);
}

static __inline struct pv_entry *
pmap_pv_alloc(void)
{
	struct pv_entry *pv;

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc()\n"));

	pv = pool_get(&pmap_pv_pool, PR_NOWAIT);

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc: %p\n", pv));

	return (pv);
}

void
pmap_pv_free(struct pv_entry *pv)
{
	if (pv->pv_ptp)
		pmap_pde_release(pv->pv_pmap, pv->pv_va, pv->pv_ptp);

	pool_put(&pmap_pv_pool, pv);
}

void
pmap_pv_enter(struct vm_page *pg, struct pv_entry *pve, struct pmap *pm,
    vaddr_t va, struct vm_page *pdep)
{
	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_enter(%p, %p, %p, 0x%lx, %p)\n",
	    pg, pve, pm, va, pdep));
	pve->pv_pmap	= pm;
	pve->pv_va	= va;
	pve->pv_ptp	= pdep;
	pve->pv_next	= pg->mdpage.pvh_list;
	pg->mdpage.pvh_list = pve;
#ifdef PMAPDEBUG
	if (pmap_check_alias(pve, va, 0))
		Debugger();
#endif
}

struct pv_entry *
pmap_pv_remove(struct vm_page *pg, struct pmap *pmap, vaddr_t va)
{
	struct pv_entry **pve, *pv;

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_remove(%p, %p, 0x%lx)\n",
	    pg, pmap, va));

	for(pv = *(pve = &pg->mdpage.pvh_list);
	    pv; pv = *(pve = &(*pve)->pv_next))
		if (pv->pv_pmap == pmap && pv->pv_va == va) {
			*pve = pv->pv_next;
			break;
		}
	return (pv);
}

const pt_entry_t hppa_pgs[] = {
	PTE_PG4K,
	PTE_PG16K,
	PTE_PG64K,
	PTE_PG256K,
	PTE_PG1M,
	PTE_PG4M,
	PTE_PG16M,
	PTE_PG64M
};

void
pmap_maphys(paddr_t spa, paddr_t epa)
{
	volatile pt_entry_t *pde, *epde, pte;
	paddr_t pa, tpa;
	int s, e, i;

	DPRINTF(PDB_INIT, ("pmap_maphys: mapping 0x%lx - 0x%lx\n", spa, epa));

	s = ffs(spa) - 12;
	e = ffs(epa) - 12;

	if (s < e || (s == e && s / 2 < nitems(hppa_pgs))) {
		i = s / 2;
		if (i > nitems(hppa_pgs))
			i = nitems(hppa_pgs);
		pa = spa;
		spa = tpa = 0x1000 << ((i + 1) * 2);
	} else if (s > e) {
		i = e / 2;
		if (i > nitems(hppa_pgs))
			i = nitems(hppa_pgs);
		epa = pa = epa & (0xfffff000 << ((i + 1) * 2));
		tpa = epa;
	} else {
		i = s / 2;
		if (i > nitems(hppa_pgs))
			i = nitems(hppa_pgs);
		pa = spa;
		spa = tpa = epa;
	}

printf("pa 0x%lx tpa 0x%lx\n", pa, tpa);
	while (pa < tpa) {
		pte = TLB_PAGE(pa) | hppa_pgs[i - 1] |
		    PTE_WRITE | PTE_ORDER | PTE_DIRTY | PTE_WIRED;
		pde = pmap_pde_get(pmap_kernel()->pm_pdir, pa);
		epde = pde + (PTE_MASK >> PTE_SHIFT) + 1;
		if (pa + (PTE_MASK + (1 << PTE_SHIFT)) > tpa)
			epde = pde + ((tpa & PTE_MASK) >> PTE_SHIFT);
printf("pde %p epde %p pte 0x%lx\n", pde, epde, (long)pte);
		for (pde += (pa & PTE_MASK) >> PTE_SHIFT; pde < epde;)
			*pde++ = pte;
		pa += PTE_MASK + (1 << PTE_SHIFT);
		pa &= ~(PTE_MASK | PAGE_MASK);
	}

	if (spa < epa)
		pmap_maphys(spa, epa);
}

void
pmap_bootstrap(vaddr_t vstart)
{
	extern int resvphysmem, __rodata_end, __data_start;
	vaddr_t va, eaddr, addr = round_page(vstart);
	struct pmap *kpm;

	DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_bootstrap(0x%lx)\n", vstart));

	uvmexp.pagesize = PAGE_SIZE;
	uvm_setpagesize();

	hppa_prot[PROT_NONE]  = PTE_ORDER|PTE_ACC_NONE;
	hppa_prot[PROT_READ]  = PTE_ORDER|PTE_READ;
	hppa_prot[PROT_WRITE] = PTE_ORDER|PTE_WRITE;
	hppa_prot[PROT_READ | PROT_WRITE] = PTE_ORDER|PTE_READ|PTE_WRITE;
	hppa_prot[PROT_EXEC]  = PTE_ORDER|PTE_EXEC;
	hppa_prot[PROT_READ | PROT_EXEC] = PTE_ORDER|PTE_READ|PTE_EXEC;
	hppa_prot[PROT_WRITE | PROT_EXEC] = PTE_ORDER|PTE_WRITE|PTE_EXEC;
	hppa_prot[PROT_READ | PROT_WRITE | PROT_EXEC] =
	    PTE_ORDER|PTE_READ|PTE_WRITE|PTE_EXEC;

	/*
	 * Initialize kernel pmap
	 */
	kpm = &kernel_pmap_store;
	bzero(kpm, sizeof(*kpm));
	uvm_objinit(&kpm->pm_obj, NULL, 1);
	kpm->pm_space = HPPA_SID_KERNEL;
	TAILQ_INIT(&kpm->pm_pglist);
	kpm->pm_pdir = (u_int32_t *)mfctl(CR_VTOP);
	fdcache(HPPA_SID_KERNEL, (vaddr_t)kpm->pm_pdir, 5 * PAGE_SIZE);

	/*
	 * Allocate various tables and structures.
	 */

	if (&__rodata_end < &__data_start) {
		physical_steal = (vaddr_t)&__rodata_end;
		physical_end = (vaddr_t)&__data_start;
		DPRINTF(PDB_INIT, ("physpool: 0x%lx @ 0x%lx\n",
		    physical_end - physical_steal, physical_steal));
	}

	/* map enough PDEs to map initial physmem */
	for (va = 0x1000000, eaddr = ptoa(physmem);
	    va < eaddr; addr += PAGE_SIZE, va += 1 << PDE_SHIFT) {
		bzero((void *)addr, PAGE_SIZE);
		fdcache(HPPA_SID_KERNEL, addr, PAGE_SIZE);
		pmap_pde_set(kpm, va, addr);
		kpm->pm_stats.resident_count++;	/* count PTP as resident */
	}

	/* map a little of initial kmem */
	for (va = VM_MIN_KERNEL_ADDRESS + ((pmap_nkpdes - 1) << PDE_SHIFT);
	    va >= VM_MIN_KERNEL_ADDRESS;
	    addr += PAGE_SIZE, va -= 1 << PDE_SHIFT) {
		bzero((void *)addr, PAGE_SIZE);
		fdcache(HPPA_SID_KERNEL, addr, PAGE_SIZE);
		pmap_pde_set(kpm, va, addr);
		kpm->pm_stats.resident_count++;	/* count PTP as resident */
	}

	pmap_maphys(0x1000000, ptoa(physmem));

	eaddr = physmem - atop(round_page(MSGBUFSIZE));
	resvphysmem = atop(addr);
	DPRINTF(PDB_INIT, ("physmem: 0x%x - 0x%lx\n", resvphysmem, eaddr));
	uvm_page_physload(0, physmem, resvphysmem, eaddr, 0);
}

void
pmap_init(void)
{
	DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init()\n"));

	pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl",
	    &pool_allocator_nointr);
	pool_init(&pmap_pv_pool, sizeof(struct pv_entry),0,0,0, "pmappv", NULL);
	pool_setlowat(&pmap_pv_pool, pmap_pvlowat);
	pool_sethiwat(&pmap_pv_pool, pmap_pvlowat * 32);

	pmap_initialized = 1;

	/*
	 * map SysCall gateways page once for everybody
	 * NB: we'll have to remap the phys memory
	 *     if we have any at SYSCALLGATE address (;
	 */
	{
		extern void gateway_page(void);
		volatile pt_entry_t *pde;

		if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, SYSCALLGATE)) &&
		    !(pde = pmap_pde_alloc(pmap_kernel(), SYSCALLGATE, NULL)))
			panic("pmap_init: cannot allocate pde");

#if 0
		pmap_pte_set(pde, SYSCALLGATE,
		    TLB_PAGE((paddr_t)gateway_page) | PTE_GATEWAY);
#else
		pmap_pte_set(pde, SYSCALLGATE,
		    TLB_PAGE((paddr_t)0x81000) | PTE_GATEWAY);
#endif
	}

	DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init(): done\n"));
}

#ifdef PMAP_STEAL_MEMORY
vaddr_t
pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp)
{
	vaddr_t va;
	int npg;

	DPRINTF(PDB_FOLLOW|PDB_PHYS,
	    ("pmap_steal_memory(0x%lx, %p, %p)\n", size, vstartp, vendp));

	size = round_page(size);
	npg = atop(size);

	if (vm_physmem[0].avail_end - vm_physmem[0].avail_start < npg)
		panic("pmap_steal_memory: no more");

	if (vstartp)
		*vstartp = VM_MIN_KERNEL_ADDRESS;
	if (vendp)
		*vendp = VM_MAX_KERNEL_ADDRESS;

	vm_physmem[0].end -= npg;
	vm_physmem[0].avail_end -= npg;
	va = ptoa(vm_physmem[0].avail_end);
	bzero((void *)va, size);

	DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_steal_memory: 0x%lx\n", va));

	return (va);
}
#else
void
pmap_virtual_space(vaddr_t *startp, vaddr_t *endp)
{
	*startp = VM_MIN_KERNEL_ADDRESS;
	*endp = VM_MAX_KERNEL_ADDRESS;
}
#endif /* PMAP_STEAL_MEMORY */

#ifdef PMAP_GROWKERNEL
vaddr_t
pmap_growkernel(vaddr_t kva)
{
	vaddr_t va;

	DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_growkernel(0x%lx)\n", kva));

	va = VM_MIN_KERNEL_ADDRESS + (pmap_nkpdes << PDE_SHIFT);
	DPRINTF(PDB_PHYS, ("pmap_growkernel: was va 0x%lx\n", va));
	if (va < kva) {
		for ( ; va < kva ; pmap_nkpdes++, va += 1 << PDE_SHIFT)
			if (uvm.page_init_done) {
				if (!pmap_pde_alloc(pmap_kernel(), va, NULL))
					break;
			} else {
				paddr_t pa;

				pa = pmap_steal_memory(PAGE_SIZE, NULL, NULL);
				if (pa)
					panic("pmap_growkernel: out of memory");
				pmap_pde_set(pmap_kernel(), va, pa);
				pmap_kernel()->pm_stats.resident_count++;
			}
	}
	DPRINTF(PDB_PHYS|PDB_VP, ("pmap_growkernel: now va 0x%lx\n", va));
	return (va);
}
#endif /* PMAP_GROWKERNEL */

struct pmap *
pmap_create(void)
{
	struct pmap *pmap;
	struct vm_page *pg;
	static pa_space_t space = 0x200;
	paddr_t pa;

	DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_create()\n"));

	pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);

	uvm_objinit(&pmap->pm_obj, NULL, 1);

	pmap->pm_ptphint = NULL;

	TAILQ_INIT(&pmap->pm_pglist);
	if (uvm_pglistalloc(2 * PAGE_SIZE, 0, VM_MIN_KERNEL_ADDRESS - 1,
	    PAGE_SIZE, 2 * PAGE_SIZE, &pmap->pm_pglist, 1, UVM_PLA_WAITOK))
		panic("pmap_create: no pages");

	pg = TAILQ_FIRST(&pmap->pm_pglist);
	atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN);
	pmap->pm_pdir = (u_int32_t *)(pa = VM_PAGE_TO_PHYS(pg));
	bzero((void *)pa, PAGE_SIZE);
	fdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);

	/* set the first PIE that's covering low 2g of the address space */
	pg = TAILQ_LAST(&pmap->pm_pglist, pglist);
	atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN);
	*pmap->pm_pdir = (pa = VM_PAGE_TO_PHYS(pg)) >> PAGE_SHIFT;
	bzero((void *)pa, PAGE_SIZE);
	fdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);

/* TODO	for (space = 1 + (arc4random() & HPPA_SID_MAX);
	    pmap_sdir_get(space); space = (space + 1) % HPPA_SID_MAX); */
	pmap->pm_space = space;
	space += 0x200;

	pmap->pm_stats.resident_count = 2;
	pmap->pm_stats.wired_count = 0;

	return (pmap);
}

void
pmap_destroy(struct pmap *pmap)
{
	struct vm_page *pg;
	paddr_t pa;
	int refs;

	DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_destroy(%p)\n", pmap));

	refs = --pmap->pm_obj.uo_refs;

	if (refs > 0)
		return;

#ifdef DIAGNOSTIC
	while ((pg = RB_ROOT(&pmap->pm_obj.memt))) {
		pt_entry_t *pde, *epde;
		struct vm_page *spg;
		struct pv_entry *pv, *npv;

		KASSERT(pg != TAILQ_FIRST(&pmap->pm_pglist));
		KASSERT(pg != TAILQ_LAST(&pmap->pm_pglist, pglist));
		pa = VM_PAGE_TO_PHYS(pg);
#ifdef PMAPDEBUG
		printf("pmap_destroy(%p): stray ptp 0x%lx w/ %u ents:",
		    pmap, pa, pg->wire_count - 1);
#endif

		pde = (pt_entry_t *)pa;
		epde = (pt_entry_t *)(pa + PAGE_SIZE);
		for (; pde < epde; pde++) {
			if (*pde == 0)
				continue;

			spg = PHYS_TO_VM_PAGE(PTE_PAGE(*pde));
			if (spg == NULL)
				continue;
			for (pv = spg->mdpage.pvh_list; pv != NULL; pv = npv) {
				npv = pv->pv_next;
				if (pv->pv_pmap == pmap) {
#ifdef PMAPDEBUG
					printf(" 0x%lx", pv->pv_va);
#endif
					pmap_remove(pmap, pv->pv_va,
					    pv->pv_va + PAGE_SIZE);
				}
			}
		}
#ifdef PMAPDEBUG
		printf("\n");
#endif
	}
#endif

	pg = TAILQ_FIRST(&pmap->pm_pglist);
	pa = VM_PAGE_TO_PHYS(pg);
	pdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
	pdtlb(HPPA_SID_KERNEL, pa);

	pg = TAILQ_LAST(&pmap->pm_pglist, pglist);
	pa = VM_PAGE_TO_PHYS(pg);
	pdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
	pdtlb(HPPA_SID_KERNEL, pa);

	uvm_pglistfree(&pmap->pm_pglist);
	TAILQ_INIT(&pmap->pm_pglist);
	pool_put(&pmap_pmap_pool, pmap);
}

/*
 * Add a reference to the specified pmap.
 */
void
pmap_reference(struct pmap *pmap)
{
	DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_reference(%p)\n", pmap));

	pmap->pm_obj.uo_refs++;
}

void
pmap_collect(struct pmap *pmap)
{
	DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_collect(%p)\n", pmap));
	/* nothing yet */
}

int
pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
{
	volatile pt_entry_t *pde;
	pt_entry_t pte;
	struct vm_page *pg, *ptp = NULL;
	struct pv_entry *pve = NULL;
	boolean_t wired = (flags & PMAP_WIRED) != 0;

	DPRINTF(PDB_FOLLOW|PDB_ENTER,
	    ("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n",
	    pmap, va, pa, prot, flags));

	if (!(pde = pmap_pde_get(pmap->pm_pdir, va)) &&
	    !(pde = pmap_pde_alloc(pmap, va, &ptp))) {
		if (flags & PMAP_CANFAIL)
			return (ENOMEM);

		panic("pmap_enter: cannot allocate pde");
	}

	if (!ptp)
		ptp = pmap_pde_ptp(pmap, pde);

	if ((pte = pmap_pte_get(pde, va))) {

		DPRINTF(PDB_ENTER,
		    ("pmap_enter: remapping 0x%lx -> 0x%lx\n", (long)pte, pa));

		pmap_pte_flush(pmap, va, pte);
		if (wired && !(pte & PTE_WIRED))
			pmap->pm_stats.wired_count++;
		else if (!wired && (pte & PTE_WIRED))
			pmap->pm_stats.wired_count--;

		if (PTE_PAGE(pte) == pa) {
			DPRINTF(PDB_FOLLOW|PDB_ENTER,
			    ("pmap_enter: same page\n"));
			goto enter;
		}

		pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
		if (pg != NULL) {
			pve = pmap_pv_remove(pg, pmap, va);
			pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
		}
	} else {
		DPRINTF(PDB_ENTER,
		    ("pmap_enter: new mapping 0x%lx -> 0x%lx\n", va, pa));
		pte = PTE_REFTRAP;
		pmap->pm_stats.resident_count++;
		if (wired)
			pmap->pm_stats.wired_count++;
		if (ptp)
			ptp->wire_count++;
	}

	if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(pa))) {
		if (!pve && !(pve = pmap_pv_alloc())) {
			if (flags & PMAP_CANFAIL)
				return (ENOMEM);
			panic("pmap_enter: no pv entries available");
		}
		pte |= pmap_prot(pmap, prot);
		if (pmap_check_alias(pg->mdpage.pvh_list, va, pte))
			pmap_page_remove(pg);
		pmap_pv_enter(pg, pve, pmap, va, ptp);
	} else if (pve)
		pmap_pv_free(pve);

enter:
	/* preserve old ref & mod */
	pte = TLB_PAGE(pa) | pmap_prot(pmap, prot) |
	    (pte & (PTE_UNCACHABLE|PTE_DIRTY|PTE_REFTRAP));
	if (IS_IOPAGE(pa))
		pte |= PTE_UNCACHABLE | PTE_ORDER;
	if (wired)
		pte |= PTE_WIRED;
	pmap_pte_set(pde, va, pte);

	DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_enter: leaving\n"));

	return (0);
}

void
pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva)
{
	struct pv_entry *pve;
	volatile pt_entry_t *pde;
	pt_entry_t pte;
	struct vm_page *pg, *ptp;
	vaddr_t pdemask;
	int batch;

	DPRINTF(PDB_FOLLOW|PDB_REMOVE,
	    ("pmap_remove(%p, 0x%lx, 0x%lx)\n", pmap, sva, eva));

	for (batch = 0; sva < eva; sva += PAGE_SIZE) {
		pdemask = sva & (PDE_MASK|PIE_MASK);
		if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) {
			sva = pdemask + PTE_MASK;
			continue;
		}
		if (pdemask == sva) {
			if (sva + (PTE_MASK + PAGE_SIZE) <= eva)
				batch = 1;
			else
				batch = 0;
		}

		if ((pte = pmap_pte_get(pde, sva))) {

			/* TODO measure here the speed tradeoff
			 * for flushing whole PT vs per-page
			 * in case of non-complete pde fill
			 */
			pmap_pte_flush(pmap, sva, pte);
			if (pte & PTE_WIRED)
				pmap->pm_stats.wired_count--;
			pmap->pm_stats.resident_count--;

			/* iff properly accounted pde will be dropped anyway */
			if (!batch)
				pmap_pte_set(pde, sva, 0);

			if (pmap_initialized &&
			    (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) {

				pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
				if ((pve = pmap_pv_remove(pg, pmap, sva)))
					pmap_pv_free(pve);
			} else {
				if (IS_IOPAGE(PTE_PAGE(pte))) {
					ptp = pmap_pde_ptp(pmap, pde);
					if (ptp != NULL)
						pmap_pde_release(pmap, sva, ptp);
				}
			}
		}
	}

	DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_remove: leaving\n"));
}

void
pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
{
	struct vm_page *pg;
	volatile pt_entry_t *pde;
	pt_entry_t pte;
	u_int tlbprot, pdemask;

	DPRINTF(PDB_FOLLOW|PDB_PMAP,
	    ("pmap_write_protect(%p, %lx, %lx, %x)\n", pmap, sva, eva, prot));

	sva = trunc_page(sva);
	tlbprot = pmap_prot(pmap, prot);

	for (pdemask = 1; sva < eva; sva += PAGE_SIZE) {
		if (pdemask != (sva & (PDE_MASK|PIE_MASK))) {
			pdemask = sva & (PDE_MASK|PIE_MASK);
			if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) {
				sva = pdemask + PTE_MASK;
				continue;
			}
		}
		if ((pte = pmap_pte_get(pde, sva))) {

			DPRINTF(PDB_PMAP,
			    ("pmap_write_protect: va=0x%lx pte=0x%lx\n",
			    sva,  (long)pte));
			/*
			 * Determine if mapping is changing.
			 * If not, nothing to do.
			 */
			if ((pte & PTE_ACC_MASK) == tlbprot)
				continue;

			pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
			if (pg != NULL)
				pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);

			pmap_pte_flush(pmap, sva, pte);
			pte &= ~PTE_ACC_MASK;
			pte |= tlbprot;
			pmap_pte_set(pde, sva, pte);
		}
	}
}

void
pmap_page_remove(struct vm_page *pg)
{
	struct pv_entry *pve, *ppve;

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove(%p)\n", pg));

	if (pg->mdpage.pvh_list == NULL)
		return;

	for (pve = pg->mdpage.pvh_list; pve;
	     pve = (ppve = pve)->pv_next, pmap_pv_free(ppve)) {
		struct pmap *pmap = pve->pv_pmap;
		vaddr_t va = pve->pv_va;
		volatile pt_entry_t *pde;
		pt_entry_t pte;

		pde = pmap_pde_get(pmap->pm_pdir, va);
		pte = pmap_pte_get(pde, va);
		pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);

		pmap_pte_flush(pmap, va, pte);
		if (pte & PTE_WIRED)
			pmap->pm_stats.wired_count--;
		pmap->pm_stats.resident_count--;

		pmap_pte_set(pde, va, 0);
	}
	pg->mdpage.pvh_list = NULL;

	DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove: leaving\n"));

}

void
pmap_unwire(struct pmap *pmap, vaddr_t	va)
{
	volatile pt_entry_t *pde;
	pt_entry_t pte = 0;

	DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire(%p, 0x%lx)\n", pmap, va));

	if ((pde = pmap_pde_get(pmap->pm_pdir, va))) {
		pte = pmap_pte_get(pde, va);

		if (pte & PTE_WIRED) {
			pte &= ~PTE_WIRED;
			pmap->pm_stats.wired_count--;
			pmap_pte_set(pde, va, pte);
		}
	}

	DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire: leaving\n"));

#ifdef DIAGNOSTIC
	if (!pte)
		panic("pmap_unwire: invalid va 0x%lx", va);
#endif
}

boolean_t
pmap_changebit(struct vm_page *pg, pt_entry_t set, pt_entry_t clear)
{
	struct pv_entry *pve;
	pt_entry_t res;

	DPRINTF(PDB_FOLLOW|PDB_BITS,
	    ("pmap_changebit(%p, %lx, %lx)\n", pg, (long)set, (long)clear));

	res = pg->mdpage.pvh_attrs = 0;
	for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) {
		struct pmap *pmap = pve->pv_pmap;
		vaddr_t va = pve->pv_va;
		volatile pt_entry_t *pde;
		pt_entry_t opte, pte;

		if ((pde = pmap_pde_get(pmap->pm_pdir, va))) {
			opte = pte = pmap_pte_get(pde, va);
#ifdef PMAPDEBUG
			if (!pte) {
				printf("pmap_changebit: zero pte for 0x%lx\n",
				    va);
				continue;
			}
#endif
			pte &= ~clear;
			pte |= set;
			pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
			res |= pmap_pvh_attrs(opte);

			if (opte != pte) {
				pmap_pte_flush(pmap, va, opte);
				pmap_pte_set(pde, va, pte);
			}
		}
	}

	return ((res & (clear | set)) != 0);
}

boolean_t
pmap_testbit(struct vm_page *pg, pt_entry_t bit)
{
	struct pv_entry *pve;
	pt_entry_t pte;

	DPRINTF(PDB_FOLLOW|PDB_BITS, ("pmap_testbit(%p, %lx)\n", pg, (long)bit));

	for(pve = pg->mdpage.pvh_list; !(pg->mdpage.pvh_attrs & bit) && pve;
	    pve = pve->pv_next) {
		pte = pmap_vp_find(pve->pv_pmap, pve->pv_va);
		pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
	}

	return ((pg->mdpage.pvh_attrs & bit) != 0);
}

boolean_t
pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pap)
{
	pt_entry_t pte;
	vaddr_t mask;

	DPRINTF(PDB_FOLLOW|PDB_EXTRACT, ("pmap_extract(%p, %lx)\n", pmap, va));

	pte = pmap_vp_find(pmap, va);

	if (pte) {
		if (pap) {
			mask = PTE_PAGE_SIZE(pte) - 1;
			*pap = PTE_PAGE(pte) | (va & mask);
		}
		return (TRUE);
	}

	return (FALSE);
}

void
pmap_activate(struct proc *p)
{
	struct pmap *pmap = p->p_vmspace->vm_map.pmap;
	struct pcb *pcb = &p->p_addr->u_pcb;

	pcb->pcb_space = pmap->pm_space;
}

void
pmap_deactivate(struct proc *p)
{

}

static __inline void
pmap_flush_page(struct vm_page *pg, int purge)
{
	struct pv_entry *pve;

	/* purge cache for all possible mappings for the pa */
	for (pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) {
		if (purge)
			pdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE);
		else
			fdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE);
		ficache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE);
		pdtlb(pve->pv_pmap->pm_space, pve->pv_va);
		pitlb(pve->pv_pmap->pm_space, pve->pv_va);
	}
}

void
pmap_zero_page(struct vm_page *pg)
{
	paddr_t pa = VM_PAGE_TO_PHYS(pg);

	DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_zero_page(%lx)\n", pa));

	pmap_flush_page(pg, 1);
	bzero((void *)pa, PAGE_SIZE);
	fdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
	pdtlb(HPPA_SID_KERNEL, pa);
}

void
pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
{
	paddr_t spa = VM_PAGE_TO_PHYS(srcpg);
	paddr_t dpa = VM_PAGE_TO_PHYS(dstpg);
	DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_copy_page(%lx, %lx)\n", spa, dpa));

	pmap_flush_page(srcpg, 0);
	pmap_flush_page(dstpg, 1);
	bcopy((void *)spa, (void *)dpa, PAGE_SIZE);
	pdcache(HPPA_SID_KERNEL, spa, PAGE_SIZE);
	fdcache(HPPA_SID_KERNEL, dpa, PAGE_SIZE);
	pdtlb(HPPA_SID_KERNEL, spa);
	pdtlb(HPPA_SID_KERNEL, dpa);
}

void
pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
{
	volatile pt_entry_t *pde;
	pt_entry_t pte, opte;

	DPRINTF(PDB_FOLLOW|PDB_ENTER,
	    ("pmap_kenter_pa(%lx, %lx, %x)\n", va, pa, prot));

	if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va)) &&
	    !(pde = pmap_pde_alloc(pmap_kernel(), va, NULL)))
		panic("pmap_kenter_pa: cannot allocate pde for va=0x%lx", va);
	opte = pmap_pte_get(pde, va);
	pte = TLB_PAGE(pa) | PTE_WIRED | PTE_REFTRAP |
	    pmap_prot(pmap_kernel(), prot);
	if (IS_IOPAGE(pa))
		pte |= PTE_UNCACHABLE | PTE_ORDER;
	if (opte)
		pmap_pte_flush(pmap_kernel(), va, opte);
	pmap_pte_set(pde, va, pte);
	pmap_kernel()->pm_stats.wired_count++;
	pmap_kernel()->pm_stats.resident_count++;

#ifdef PMAPDEBUG
	{
		struct vm_page *pg;

		if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) {

			if (pmap_check_alias(pg->mdpage.pvh_list, va, pte))
				Debugger();
		}
	}
#endif
	DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_kenter_pa: leaving\n"));
}

void
pmap_kremove(vaddr_t va, vsize_t size)
{
	struct pv_entry *pve;
	vaddr_t eva, pdemask;
	volatile pt_entry_t *pde;
	pt_entry_t pte;
	struct vm_page *pg;

	DPRINTF(PDB_FOLLOW|PDB_REMOVE,
	    ("pmap_kremove(%lx, %lx)\n", va, size));
#ifdef PMAPDEBUG
	if (va < ptoa(physmem)) {
		printf("pmap_kremove(%lx, %lx): unmapping physmem\n", va, size);
		return;
	}
#endif

	for (pdemask = 1, eva = va + size; va < eva; va += PAGE_SIZE) {
		if (pdemask != (va & (PDE_MASK|PIE_MASK))) {
			pdemask = va & (PDE_MASK|PIE_MASK);
			if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va))) {
				va = pdemask + PTE_MASK;
				continue;
			}
		}
		if (!(pte = pmap_pte_get(pde, va))) {
#ifdef DEBUG
			printf("pmap_kremove: unmapping unmapped 0x%lx\n", va);
#endif
			continue;
		}

		pmap_pte_flush(pmap_kernel(), va, pte);
		pmap_pte_set(pde, va, 0);
		if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) {

			pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
			/* just in case we have enter/kenter mismatch */
			if ((pve = pmap_pv_remove(pg, pmap_kernel(), va)))
				pmap_pv_free(pve);
		}
	}

	DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_kremove: leaving\n"));
}

void
pmap_proc_iflush(struct proc *p, vaddr_t va, vsize_t len)
{
	struct pmap *pmap = p->p_vmspace->vm_map.pmap;

	fdcache(pmap->pm_space, va, len);
	sync_caches();
	ficache(pmap->pm_space, va, len);
	sync_caches();
}

struct vm_page *
pmap_unmap_direct(vaddr_t va)
{
	fdcache(HPPA_SID_KERNEL, va, PAGE_SIZE);
	pdtlb(HPPA_SID_KERNEL, va);
	return (PHYS_TO_VM_PAGE(va));
}


code:
/*	$OpenBSD: process_machdep.c,v 1.3 2011/09/22 13:50:30 deraadt Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/user.h>

int
process_read_regs(struct proc *p, struct reg *regs)
{
	struct trapframe *tf = p->p_md.md_regs;

	regs->r_regs[0] = tf->tf_sar;
	bcopy(&tf->tf_r1, &regs->r_regs[1], 31*8);
	regs->r_pc  = tf->tf_iioq[0];
	regs->r_npc = tf->tf_iioq[1];

	return (0);
}

int
process_read_fpregs(struct proc *p, struct fpreg *fpregs)
{
	fpu_proc_save(p);

	bcopy(&p->p_addr->u_pcb.pcb_fpstate->hfp_regs, fpregs, 32 * 8);

	return (0);
}

#ifdef PTRACE

int
process_write_regs(struct proc *p, struct reg *regs)
{
	struct trapframe *tf = p->p_md.md_regs;

	tf->tf_sar = regs->r_regs[0];
	bcopy(&regs->r_regs[1], &tf->tf_r1, 31*8);
	tf->tf_iioq[0] = regs->r_pc | 3;
	tf->tf_iioq[1] = regs->r_npc | 3;

	return (0);
}

int
process_write_fpregs(struct proc *p, struct fpreg *fpregs)
{
	fpu_proc_flush(p);

	bcopy(fpregs, &p->p_addr->u_pcb.pcb_fpstate->hfp_regs, 32 * 8);

	return (0);
}

int
process_sstep(struct proc *p, int sstep)
{
	if (sstep)
		return (EINVAL);

	return (0);
}

int
process_set_pc(struct proc *p, caddr_t addr)
{
	p->p_md.md_regs->tf_iioq[1] = 4 +
	    (p->p_md.md_regs->tf_iioq[0] = (register_t)addr | 3);

	return (0);
}

#endif	/* PTRACE */

license: unknown


code:
/*	$OpenBSD: sys_machdep.c,v 1.1 2005/04/01 10:40:47 mickey Exp $	*/

/*
 * Copyright (c) 1982, 1986, 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. 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.
 *
 *	@(#)sys_machdep.c	8.2 (Berkeley) 1/13/94
 */

#include <sys/param.h>
#include <sys/systm.h>

#include <sys/mount.h>
#include <sys/syscallargs.h>

int
sys_sysarch(p, v, retval)
	struct proc *p;
	void *v;
	register_t *retval;
{
	struct sys_sysarch_args /* {
		syscallarg(int) op;
		syscallarg(char *) parms;
	} */ *uap = v;
	int error = 0;

	switch (SCARG(uap, op)) {
	default:
		error = EINVAL;
		break;
	}
	return (error);
}


code:
/*	$OpenBSD: trap.c,v 1.41 2014/11/16 12:30:57 deraadt Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#undef TRAPDEBUG

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/syscall_mi.h>

#include <uvm/uvm_extern.h>

#include <machine/autoconf.h>
#include <machine/cpufunc.h>
#include <machine/psl.h>

#ifdef DDB
#include <machine/db_machdep.h>
#endif

#ifdef TRAPDEBUG
#include <ddb/db_output.h>
#endif

static __inline int inst_store(u_int ins) {
	return (ins & 0xf0000000) == 0x60000000 ||	/* stb/sth/stw */
	       (ins & 0xfc000000) == 0x70000000 ||	/* std/fstd */
	       (ins & 0xfc000000) == 0x78000000 ||	/* fstw */
	       (ins & 0xfc000000) == 0x7c000000 ||	/* stw/fstw */
	       (ins & 0xfc000200) == 0x24000200 ||	/* cstw */
	       (ins & 0xfc000200) == 0x2c000200 ||	/* cstd */
	       (ins & 0xfc001300) == 0x0c001200 ||	/* stb/sth/stw/std */
	       (ins & 0xfc001380) == 0x0c001300 ||	/* stby/stdby */
	       (ins & 0xfc0003c0) == 0x0c0001c0 ||	/* ldcw */
	       (ins & 0xfc0003c0) == 0x0c000140;	/* ldcd */
}

void	ast(struct proc *);

const char *trap_type[] = {
	"invalid",
	"HPMC",
	"power failure",
	"recovery counter",
	"external interrupt",
	"LPMC",
	"ITLB miss fault",
	"instruction protection",
	"Illegal instruction",
	"break instruction",
	"privileged operation",
	"privileged register",
	"overflow",
	"conditional",
	"assist exception",
	"DTLB miss",
	"ITLB non-access miss",
	"DTLB non-access miss",
	"data protection/rights/alignment",
	"data break",
	"TLB dirty",
	"page reference",
	"assist emulation",
	"higher-priv transfer",
	"lower-priv transfer",
	"taken branch",
	"data access rights",
	"data protection",
	"unaligned data ref",
};
int trap_types = sizeof(trap_type)/sizeof(trap_type[0]);

int want_resched, astpending;

#define	frame_regmap(tf,r)	(((register_t *)(tf))[hppa64_regmap[(r)]])
u_char hppa64_regmap[32] = {
	offsetof(struct trapframe, tf_pad[0]) / 8,	/* r0 XXX */
	offsetof(struct trapframe, tf_r1) / 8,
	offsetof(struct trapframe, tf_rp) / 8,
	offsetof(struct trapframe, tf_r3) / 8,
	offsetof(struct trapframe, tf_r4) / 8,
	offsetof(struct trapframe, tf_r5) / 8,
	offsetof(struct trapframe, tf_r6) / 8,
	offsetof(struct trapframe, tf_r7) / 8,
	offsetof(struct trapframe, tf_r8) / 8,
	offsetof(struct trapframe, tf_r9) / 8,
	offsetof(struct trapframe, tf_r10) / 8,
	offsetof(struct trapframe, tf_r11) / 8,
	offsetof(struct trapframe, tf_r12) / 8,
	offsetof(struct trapframe, tf_r13) / 8,
	offsetof(struct trapframe, tf_r14) / 8,
	offsetof(struct trapframe, tf_r15) / 8,
	offsetof(struct trapframe, tf_r16) / 8,
	offsetof(struct trapframe, tf_r17) / 8,
	offsetof(struct trapframe, tf_r18) / 8,
	offsetof(struct trapframe, tf_args[7]) / 8,
	offsetof(struct trapframe, tf_args[6]) / 8,
	offsetof(struct trapframe, tf_args[5]) / 8,
	offsetof(struct trapframe, tf_args[4]) / 8,
	offsetof(struct trapframe, tf_args[3]) / 8,
	offsetof(struct trapframe, tf_args[2]) / 8,
	offsetof(struct trapframe, tf_args[1]) / 8,
	offsetof(struct trapframe, tf_args[0]) / 8,
	offsetof(struct trapframe, tf_dp) / 8,
	offsetof(struct trapframe, tf_ret0) / 8,
	offsetof(struct trapframe, tf_ret1) / 8,
	offsetof(struct trapframe, tf_sp) / 8,
	offsetof(struct trapframe, tf_r31) / 8,
};

void
ast(struct proc *p)
{
	if (astpending) {
		astpending = 0;
		uvmexp.softs++;
		mi_ast(p, want_resched);
	}
}

void
trap(int type, struct trapframe *frame)
{
	struct proc *p = curproc;
	vaddr_t va;
	struct vm_map *map;
	struct vmspace *vm;
	register vm_prot_t vftype;
	register pa_space_t space;
	union sigval sv;
	u_int opcode;
	int ret, trapnum;
	const char *tts;
	vm_fault_t fault = VM_FAULT_INVALID;
#ifdef DIAGNOSTIC
	long oldcpl = curcpu()->ci_cpl;
#endif
	u_long mask;

	trapnum = type & ~T_USER;
	opcode = frame->tf_iir;
	if (trapnum <= T_EXCEPTION || trapnum == T_HIGHERPL ||
	    trapnum == T_LOWERPL || trapnum == T_TAKENBR ||
	    trapnum == T_IDEBUG || trapnum == T_PERFMON ||
	    trapnum == T_IPROT) {
		va = frame->tf_iioq[0];
		space = frame->tf_iisq[0];
		vftype = PROT_EXEC;
	} else {
		va = frame->tf_ior;
		space = frame->tf_isr;
		if (va == frame->tf_iioq[0])
			vftype = PROT_EXEC;
		else if (inst_store(opcode))
			vftype = PROT_WRITE;
		else
			vftype = PROT_READ;
	}

	if (frame->tf_flags & TFF_LAST)
		p->p_md.md_regs = frame;

	if (trapnum > trap_types)
		tts = "reserved";
	else
		tts = trap_type[trapnum];

#ifdef TRAPDEBUG
	if (trapnum != T_INTERRUPT && trapnum != T_IBREAK)
		db_printf("trap: %x, %s for %x:%lx at %x:%lx, fl=%x, fp=%p\n",
		    type, tts, space, va, frame->tf_iisq[0],
		    frame->tf_iioq[0], frame->tf_flags, frame);
	else if (trapnum  == T_IBREAK)
		db_printf("trap: break instruction %x:%x at %x:%lx, fp=%p\n",
		    opcode & 0x1f, (opcode >> 13) & 0x1fff,
		    frame->tf_iisq[0], frame->tf_iioq[0], frame);

	{
		extern int etext;
		if (frame < (struct trapframe *)&etext) {
			printf("trap: bogus frame ptr %p\n", frame);
			goto dead_end;
		}
	}
#endif
	if (trapnum != T_INTERRUPT) {
		uvmexp.traps++;
		mtctl(frame->tf_eiem, CR_EIEM);
	        ssm(PSL_I, mask);
	}

	if (type & T_USER)
		refreshcreds(p);

	switch (type) {
	case T_NONEXIST:
	case T_NONEXIST | T_USER:
		/* we've got screwed up by the central scrutinizer */
		printf("trap: elvis has just left the building!\n");
		goto dead_end;

	case T_RECOVERY:
	case T_RECOVERY | T_USER:
		/* XXX will implement later */
		printf("trap: handicapped");
		goto dead_end;

#ifdef DIAGNOSTIC
	case T_EXCEPTION:
		panic("FPU/SFU emulation botch");

		/* these just can't happen ever */
	case T_PRIV_OP:
	case T_PRIV_REG:
		/* these just can't make it to the trap() ever */
	case T_HPMC:
	case T_HPMC | T_USER:
#endif
	case T_IBREAK:
	case T_DATALIGN:
	case T_DBREAK:
	dead_end:
#ifdef DDB
		if (kdb_trap (type, va, frame)) {
			if (type == T_IBREAK) {
				/* skip break instruction */
				frame->tf_iioq[0] = frame->tf_iioq[1];
				frame->tf_iioq[1] += 4;
			}
			return;
		}
#else
		if (type == T_DATALIGN)
			panic ("trap: %s at 0x%lx", tts, va);
		else
			panic ("trap: no debugger for \"%s\" (%d)", tts, type);
#endif
		break;

	case T_IBREAK | T_USER:
	case T_DBREAK | T_USER:
		/* pass to user debugger */
		trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv);
		break;

	case T_EXCEPTION | T_USER: {
		struct hppa_fpstate *hfp;
		u_int64_t *fpp;
		u_int32_t *pex;
		int i, flt;

		hfp = (struct hppa_fpstate *)frame->tf_cr30;
		fpp = (u_int64_t *)&hfp->hfp_regs;

		pex = (u_int32_t *)&fpp[0];
		for (i = 0, pex++; i < 7 && !*pex; i++, pex++);
		flt = 0;
		if (i < 7) {
			u_int32_t stat = HPPA_FPU_OP(*pex);
			if (stat & HPPA_FPU_UNMPL)
				flt = FPE_FLTINV;
			else if (stat & (HPPA_FPU_V << 1))
				flt = FPE_FLTINV;
			else if (stat & (HPPA_FPU_Z << 1))
				flt = FPE_FLTDIV;
			else if (stat & (HPPA_FPU_I << 1))
				flt = FPE_FLTRES;
			else if (stat & (HPPA_FPU_O << 1))
				flt = FPE_FLTOVF;
			else if (stat & (HPPA_FPU_U << 1))
				flt = FPE_FLTUND;
			/* still left: under/over-flow w/ inexact */

			/* cleanup exceptions (XXX deliver all ?) */
			while (i++ < 7)
				*pex++ = 0;
		}
		/* reset the trap flag, as if there was none */
		fpp[0] &= ~(((u_int64_t)HPPA_FPU_T) << 32);
		/* flush out, since load is done from phys, only 4 regs */
		fdcache(HPPA_SID_KERNEL, (vaddr_t)fpp, 8 * 4);

		sv.sival_int = va;
		trapsignal(p, SIGFPE, type &~ T_USER, flt, sv);
		}
		break;

	case T_EMULATION:
		panic("trap: emulation trap in the kernel");
		break;

	case T_EMULATION | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGILL, type &~ T_USER, ILL_COPROC, sv);
		break;

	case T_OVERFLOW | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv);
		break;

	case T_CONDITION | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv);
		break;

	case T_PRIV_OP | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv);
		break;

	case T_PRIV_REG | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv);
		break;

		/* these should never got here */
	case T_HIGHERPL | T_USER:
	case T_LOWERPL | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
		break;

	case T_DPROT | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
		break;

	case T_ITLBMISSNA:
	case T_ITLBMISSNA | T_USER:
	case T_DTLBMISSNA:
	case T_DTLBMISSNA | T_USER:
		if (space == HPPA_SID_KERNEL)
			map = kernel_map;
		else {
			vm = p->p_vmspace;
			map = &vm->vm_map;
		}

		/* dig probei?,[rw] insns */
		if ((opcode & 0xfc001f80) == 0x04001180) {
			int pl;

			if (opcode & 0x2000)
				pl = (opcode >> 16) & 3;
			else
				pl = frame_regmap(frame,
				    (opcode >> 16) & 0x1f) & 3;

			if ((type & T_USER && space == HPPA_SID_KERNEL) ||
			    (type & T_USER && !pl) ||
			    (type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
			    uvm_fault(map, trunc_page(va), fault,
			     opcode & 0x40? PROT_WRITE : PROT_READ)) {
				frame_regmap(frame, opcode & 0x1f) = 0;
				frame->tf_ipsw |= PSL_N;
			}
		} else if (type & T_USER) {
			sv.sival_int = va;
			trapsignal(p, SIGILL, type & ~T_USER, ILL_ILLTRP, sv);
		} else
			panic("trap: %s @ 0x%lx:0x%lx for 0x%x:0x%lx irr 0x%08x",
			    tts, frame->tf_iisq[0], frame->tf_iioq[0],
			    space, va, opcode);
		break;

	case T_TLB_DIRTY:
	case T_TLB_DIRTY | T_USER:
	case T_DATACC:
	case T_DATACC | T_USER:
	case T_IPROT | T_USER:
		fault = VM_FAULT_PROTECT;
	case T_ITLBMISS:
	case T_ITLBMISS | T_USER:
	case T_DTLBMISS:
	case T_DTLBMISS | T_USER:
		/*
		 * it could be a kernel map for exec_map faults
		 */
		if (space == HPPA_SID_KERNEL)
			map = kernel_map;
		else {
			vm = p->p_vmspace;
			map = &vm->vm_map;
		}

		/*
		 * user faults out of user addr space are always a fail,
		 * this happens on va >= VM_MAXUSER_ADDRESS, where
		 * space id will be zero and therefore cause
		 * a misbehave lower in the code.
		 *
		 * also check that faulted space id matches the curproc.
		 */
		if ((type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
		    (type & T_USER && map->pmap->pm_space != space)) {
			sv.sival_int = va;
			trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
			break;
		}

		ret = uvm_fault(map, trunc_page(va), fault, vftype);

		/*
		 * If this was a stack access we keep track of the maximum
		 * accessed stack size.  Also, if uvm_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 (space != HPPA_SID_KERNEL &&
		    va < (vaddr_t)vm->vm_minsaddr) {
			if (ret == 0)
				uvm_grow(p, va);
			else if (ret == EACCES)
				ret = EFAULT;
		}

		if (ret != 0) {
			if (type & T_USER) {
				sv.sival_int = va;
				trapsignal(p, SIGSEGV, vftype,
				    ret == EACCES? SEGV_ACCERR : SEGV_MAPERR,
				    sv);
			} else {
				if (p && p->p_addr->u_pcb.pcb_onfault) {
					frame->tf_iioq[1] = 4 +
					    (frame->tf_iioq[0] =
						p->p_addr->u_pcb.pcb_onfault);
#ifdef DDB
					frame->tf_iir = 0;
#endif
				} else {
					printf("trap: "
					    "uvm_fault(%p, %lx, %d, %d): %d\n",
					    map, va, fault, vftype, ret);
					goto dead_end;
				}
			}
		}
		break;

	case T_DATALIGN | T_USER:
		sv.sival_int = va;
		trapsignal(p, SIGBUS, vftype, BUS_ADRALN, sv);
		break;

	case T_INTERRUPT:
	case T_INTERRUPT | T_USER:
		cpu_intr(frame);
		break;

	case T_CONDITION:
		panic("trap: divide by zero in the kernel");
		break;

	case T_ILLEGAL:
	case T_ILLEGAL | T_USER:
		/* see if it's a SPOP1,,0 */
		if ((opcode & 0xfffffe00) == 0x10000200) {
			frame_regmap(frame, opcode & 0x1f) = 0;
			frame->tf_ipsw |= PSL_N;
			break;
		}
		if (type & T_USER) {
			sv.sival_int = va;
			trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv);
			break;
		}
		/* FALLTHROUGH */

	case T_LOWERPL:
	case T_DPROT:
	case T_IPROT:
	case T_OVERFLOW:
	case T_HIGHERPL:
	case T_TAKENBR:
	case T_POWERFAIL:
	case T_LPMC:
	case T_PAGEREF:
	case T_DATAPID:
	case T_DATAPID | T_USER:
		if (0 /* T-chip */) {
			break;
		}
		/* FALLTHROUGH to unimplemented */
	default:
#ifdef TRAPDEBUG
		if (kdb_trap(type, va, frame))
			return;
#endif
		panic("trap: unimplemented \'%s\' (%d)", tts, trapnum);
	}

#ifdef DIAGNOSTIC
	if (curcpu()->ci_cpl != oldcpl)
		printf("WARNING: SPL (%d) NOT LOWERED ON "
		    "TRAP (%d) EXIT\n", curcpu()->ci_cpl, trapnum);
#endif

	if (trapnum != T_INTERRUPT)
		splx(curcpu()->ci_cpl);	/* process softints */

	/*
	 * in case we were interrupted from the syscall gate page
	 * treat this as we were not really running user code no more
	 * for weird things start to happen on return to the userland
	 * and also see a note in locore.S:TLABEL(all)
	 */
	if ((type & T_USER) &&
	    (frame->tf_iioq[0] & ~PAGE_MASK) != SYSCALLGATE) {
		ast(p);
		userret(p);
	}
}

void
child_return(void *arg)
{
	struct proc *p = (struct proc *)arg;
	struct trapframe *tf = p->p_md.md_regs;

	/*
	 * Set up return value registers as libc:fork() expects
	 */
	tf->tf_ret0 = 0;
	tf->tf_ret1 = 1;	/* ischild */
	tf->tf_r1 = 0;		/* errno */

	ast(p);

	mi_child_return(p);
}

void	syscall(struct trapframe *frame);

/*
 * call actual syscall routine
 */
void
syscall(struct trapframe *frame)
{
	register struct proc *p = curproc;
	register const struct sysent *callp;
	int nsys, code, error;
	register_t args[8], rval[2];
#ifdef DIAGNOSTIC
	long oldcpl = curcpu()->ci_cpl;
#endif

	uvmexp.syscalls++;

	if (!USERMODE(frame->tf_iioq[0]))
		panic("syscall");

	p->p_md.md_regs = frame;
	nsys = p->p_p->ps_emul->e_nsysent;
	callp = p->p_p->ps_emul->e_sysent;

	switch (code = frame->tf_r1) {
	case SYS_syscall:
	case SYS___syscall:
		code = frame->tf_args[0];
		args[0] = frame->tf_args[1];
		args[1] = frame->tf_args[2];
		args[2] = frame->tf_args[3];
		args[3] = frame->tf_args[4];
		args[4] = frame->tf_args[5];
		args[5] = frame->tf_args[6];
		args[6] = frame->tf_args[7];
		break;
	default:
		args[0] = frame->tf_args[0];
		args[1] = frame->tf_args[1];
		args[2] = frame->tf_args[2];
		args[3] = frame->tf_args[3];
		args[4] = frame->tf_args[4];
		args[5] = frame->tf_args[5];
		args[6] = frame->tf_args[6];
		args[7] = frame->tf_args[7];
		break;
	}

	if (code < 0 || code >= nsys)
		callp += p->p_p->ps_emul->e_nosys;	/* bad syscall # */
	else
		callp += code;

	rval[0] = 0;
	rval[1] = frame->tf_ret1;

	error = mi_syscall(p, code, callp, args, rval);

	switch (error) {
	case 0:
		frame->tf_ret0 = rval[0];
		frame->tf_ret1 = rval[1];
		frame->tf_r1 = 0;
		break;
	case ERESTART:
		frame->tf_iioq[0] -= 16;
		frame->tf_iioq[1] -= 16;
	case EJUSTRETURN:
		break;
	default:
		frame->tf_r1 = error;
		frame->tf_ret0 = error;
		frame->tf_ret1 = 0;
		break;
	}

	ast(p);

	mi_syscall_return(p, code, error, rval);

#ifdef DIAGNOSTIC
	if (curcpu()->ci_cpl != oldcpl) {
		printf("WARNING: SPL (0x%x) NOT LOWERED ON "
		    "syscall(0x%x, 0x%lx, 0x%lx, 0x%lx...) EXIT, PID %d\n",
		    curcpu()->ci_cpl, code, args[0], args[1], args[2],
		    p->p_pid);
		curcpu()->ci_cpl = oldcpl;
	}
#endif
	splx(curcpu()->ci_cpl);	/* process softints */
}


code:
/*	$OpenBSD: vm_machdep.c,v 1.22 2015/05/05 02:13:46 guenther Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/malloc.h>
#include <sys/buf.h>
#include <sys/vnode.h>
#include <sys/user.h>
#include <sys/ptrace.h>
#include <sys/exec.h>
#include <sys/pool.h>

#include <uvm/uvm_extern.h>

#include <machine/psl.h>
#include <machine/pmap.h>
#include <machine/pcb.h>

extern struct pool hppa_fppl;

void
cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
    void (*func)(void *), void *arg)
{
	extern register_t switch_tramp_p;

	struct pcb *pcbp;
	struct trapframe *tf;
	register_t sp, osp;

#ifdef DIAGNOSTIC
	if (round_page(sizeof(struct user) + sizeof(*tf)) > PAGE_SIZE)
		panic("USPACE too small for user");
#endif
	fpu_proc_save(p1);

	pcbp = &p2->p_addr->u_pcb;
	bcopy(&p1->p_addr->u_pcb, pcbp, sizeof(*pcbp));
	/* space is cached for the copy{in,out}'s pleasure */
	pcbp->pcb_space = p2->p_vmspace->vm_map.pmap->pm_space;
	pcbp->pcb_fpstate = pool_get(&hppa_fppl, PR_WAITOK);
	*pcbp->pcb_fpstate = *p1->p_addr->u_pcb.pcb_fpstate;
	/* reset any of the pending FPU exceptions from parent */
	pcbp->pcb_fpstate->hfp_regs.fpr_regs[0] =
	    HPPA_FPU_FORK(pcbp->pcb_fpstate->hfp_regs.fpr_regs[0]);
	pcbp->pcb_fpstate->hfp_regs.fpr_regs[1] = 0;
	pcbp->pcb_fpstate->hfp_regs.fpr_regs[2] = 0;
	pcbp->pcb_fpstate->hfp_regs.fpr_regs[3] = 0;

	sp = (register_t)p2->p_addr + PAGE_SIZE;
	p2->p_md.md_regs = tf = (struct trapframe *)sp;
	sp += sizeof(struct trapframe);
	bcopy(p1->p_md.md_regs, tf, sizeof(*tf));

	tf->tf_vtop = (paddr_t)p2->p_vmspace->vm_map.pmap->pm_pdir;
	tf->tf_cr30 = (paddr_t)pcbp->pcb_fpstate;

	tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 =
	tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 =
	tf->tf_iisq[0] = tf->tf_iisq[1] =
		p2->p_vmspace->vm_map.pmap->pm_space;
	tf->tf_pidr1 = tf->tf_pidr2 = pmap_sid2pid(tf->tf_sr0);

	/*
	 * theoretically these could be inherited from the father,
	 * but just in case.
	 */
	tf->tf_sr7 = HPPA_SID_KERNEL;
	tf->tf_eiem = mfctl(CR_EIEM);
	tf->tf_ipsw = PSL_C | PSL_Q | PSL_P | PSL_D | PSL_I /* | PSL_L */ |
	    PSL_O | PSL_W;

	/*
	 * If specified, give the child a different stack.
	 */
	if (stack != NULL)
		setstack(tf, (u_long)stack, 0);	/* XXX ignore error? */

	/*
	 * Build stack frames for the cpu_switchto & co.
	 */
	osp = sp + HPPA_FRAME_SIZE;
	*(register_t*)(osp - HPPA_FRAME_SIZE) = 0;
	*(register_t*)(osp + HPPA_FRAME_RP) = switch_tramp_p;
	*(register_t*)(osp) = (osp - HPPA_FRAME_SIZE);

	sp = osp + HPPA_FRAME_SIZE + 20*8; /* frame + callee-saved registers */
	*(register_t*)(sp - HPPA_FRAME_SIZE + 0) = (register_t)arg;
	*(register_t*)(sp - HPPA_FRAME_SIZE + 8) = KERNMODE(func);
	*(register_t*)(sp - HPPA_FRAME_SIZE + 16) = 0;	/* cpl */
	pcbp->pcb_ksp = sp;
}

void
cpu_exit(struct proc *p)
{
	struct pcb *pcb = &p->p_addr->u_pcb;

	fpu_proc_flush(p);

	pool_put(&hppa_fppl, pcb->pcb_fpstate);

	pmap_deactivate(p);
	sched_exit(p);
}

/*
 * Map an IO request into kernel virtual address space.
 */
void
vmapbuf(struct buf *bp, vsize_t len)
{
	struct pmap *pm = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map);
	vaddr_t kva, uva;
	vsize_t size, off;

#ifdef DIAGNOSTIC
	if ((bp->b_flags & B_PHYS) == 0)
		panic("vmapbuf");
#endif
	bp->b_saveaddr = bp->b_data;
	uva = trunc_page((vaddr_t)bp->b_data);
	off = (vaddr_t)bp->b_data - uva;
	size = round_page(off + len);

	kva = uvm_km_valloc_prefer_wait(phys_map, size, uva);
	bp->b_data = (caddr_t)(kva + off);
	while (size > 0) {
		paddr_t pa;

		if (pmap_extract(pm, uva, &pa) == FALSE)
			panic("vmapbuf: null page frame");
		else
			pmap_kenter_pa(kva, pa, PROT_READ | PROT_WRITE);
		uva += PAGE_SIZE;
		kva += PAGE_SIZE;
		size -= PAGE_SIZE;
	}
	pmap_update(pmap_kernel());
}

/*
 * Unmap IO request from the kernel virtual address space.
 */
void
vunmapbuf(struct buf *bp, vsize_t len)
{
	vaddr_t addr, off;

#ifdef DIAGNOSTIC
	if ((bp->b_flags & B_PHYS) == 0)
		panic("vunmapbuf");
#endif
	addr = trunc_page((vaddr_t)bp->b_data);
	off = (vaddr_t)bp->b_data - addr;
	len = round_page(off + len);
	pmap_kremove(addr, len);
	pmap_update(pmap_kernel());
	uvm_km_free_wakeup(phys_map, addr, len);
	bp->b_data = bp->b_saveaddr;
	bp->b_saveaddr = NULL;
}


code:
/*	$OpenBSD: wscons_machdep.c,v 1.1 2005/04/01 10:40:48 mickey Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/conf.h>

#include <dev/cons.h>

#include "wsdisplay.h"
#if NWSDISPLAY > 0
#include <dev/wscons/wsdisplayvar.h>
#endif

#include "wskbd.h"
#if NWSKBD > 0
#include <dev/wscons/wskbdvar.h>
#endif

cons_decl(ws);

void
wscnprobe(struct consdev *cp)
{
	/*
	 * Due to various device probe restrictions, the wscons console
	 * can never be enabled early during boot.
	 * It will be enabled as soon as enough wscons components get
	 * attached.
	 * So do nothing there, the switch will occur in
	 * wsdisplay_emul_attach() later.
	 */
}

void
wscninit(struct consdev *cp)
{
}

void
wscnputc(dev_t dev, int i)
{
#if NWSDISPLAY > 0
	wsdisplay_cnputc(dev, i);
#endif
}

int
wscngetc(dev_t dev)
{
#if NWSKBD > 0
	return (wskbd_cngetc(dev));
#else
	return (0);
#endif
}

void
wscnpollc(dev_t dev, int on)
{
#if NWSKBD > 0
	wskbd_cnpollc(dev, on);
#endif
}


code:
/*	$OpenBSD: _float.h,v 1.1 2012/06/26 16:12:44 deraadt Exp $	*/

/*
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _MACHINE__FLOAT_H_
#define _MACHINE__FLOAT_H_

#define __FLT_RADIX		2
#define __FLT_ROUNDS		__flt_rounds()
#define __FLT_EVAL_METHOD	0		/* no promotions */

#define __FLT_MANT_DIG		24
#define __FLT_EPSILON		1.19209290E-07F
#define __FLT_DIG		6
#define __FLT_MIN_EXP		(-125)
#define __FLT_MIN		1.17549435E-38F
#define __FLT_MIN_10_EXP	(-37)
#define __FLT_MAX_EXP		128
#define __FLT_MAX		3.40282347E+38F
#define __FLT_MAX_10_EXP	38

#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

#define __DECIMAL_DIG		17

#endif /* _MACHINE__FLOAT_H_ */


code:
/*	$OpenBSD: _types.h,v 1.17 2014/03/19 05:14:13 guenther 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. 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
 *	@(#)ansi.h	8.2 (Berkeley) 1/4/94
 */

#ifndef _MACHINE__TYPES_H_
#define _MACHINE__TYPES_H_

#if defined(_KERNEL)
typedef struct label_t {
	long	val[20];
} label_t;
#endif

/*
 * _ALIGN(p) rounds p (pointer or byte index) up to a correctly-aligned
 * value for all data types (int, long, ...).   The result is an
 * unsigned 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	_STACKALIGNBYTES	_ALIGNBYTES
#define	_ALIGN(p)		(((unsigned long)(p) + _ALIGNBYTES) & ~_ALIGNBYTES)
#define	_ALIGNED_POINTER(p,t)	((((unsigned long)(p)) & (sizeof(t) - 1)) == 0)

typedef unsigned long		hppa_hpa_t;	/* XXX */
typedef unsigned long		hppa_spa_t;	/* XXX */
typedef unsigned int		pa_space_t;	/* XXX */

/* 7.18.1.1 Exact-width integer types */
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;
/* LONGLONG */
typedef	long long		__int64_t;
/* LONGLONG */
typedef	unsigned long long	__uint64_t;

/* 7.18.1.2 Minimum-width integer types */
typedef	__int8_t		__int_least8_t;
typedef	__uint8_t		__uint_least8_t;
typedef	__int16_t		__int_least16_t;
typedef	__uint16_t		__uint_least16_t;
typedef	__int32_t		__int_least32_t;
typedef	__uint32_t		__uint_least32_t;
typedef	__int64_t		__int_least64_t;
typedef	__uint64_t		__uint_least64_t;

/* 7.18.1.3 Fastest minimum-width integer types */
typedef	__int32_t		__int_fast8_t;
typedef	__uint32_t		__uint_fast8_t;
typedef	__int32_t		__int_fast16_t;
typedef	__uint32_t		__uint_fast16_t;
typedef	__int32_t		__int_fast32_t;
typedef	__uint32_t		__uint_fast32_t;
typedef	__int64_t		__int_fast64_t;
typedef	__uint64_t		__uint_fast64_t;
#define	__INT_FAST8_MIN		INT32_MIN
#define	__INT_FAST16_MIN	INT32_MIN
#define	__INT_FAST32_MIN	INT32_MIN
#define	__INT_FAST64_MIN	INT64_MIN
#define	__INT_FAST8_MAX		INT32_MAX
#define	__INT_FAST16_MAX	INT32_MAX
#define	__INT_FAST32_MAX	INT32_MAX
#define	__INT_FAST64_MAX	INT64_MAX
#define	__UINT_FAST8_MAX	UINT32_MAX
#define	__UINT_FAST16_MAX	UINT32_MAX
#define	__UINT_FAST32_MAX	UINT32_MAX
#define	__UINT_FAST64_MAX	UINT64_MAX

/* 7.18.1.4 Integer types capable of holding object pointers */
typedef	long			__intptr_t;
typedef	unsigned long		__uintptr_t;

/* 7.18.1.5 Greatest-width integer types */
typedef	__int64_t		__intmax_t;
typedef	__uint64_t		__uintmax_t;

/* Register size */
typedef long			__register_t;

/* VM system types */
typedef unsigned long		__vaddr_t;
typedef unsigned long		__paddr_t;
typedef unsigned long		__vsize_t;
typedef unsigned long		__psize_t;

/* Standard system types */
typedef double			__double_t;
typedef float			__float_t;
typedef long			__ptrdiff_t;
typedef	unsigned long		__size_t;
typedef	long			__ssize_t;
typedef	__builtin_va_list	__va_list;

/* Wide character support types */
#ifndef __cplusplus
typedef	int			__wchar_t;
#endif
typedef int			__wint_t;
typedef	int			__rune_t;
typedef	void *			__wctrans_t;
typedef	void *			__wctype_t;

#endif	/* _MACHINE__TYPES_H_ */


code:
/*	$OpenBSD: asm.h,v 1.3 2013/03/28 17:41:04 martynas Exp $	*/

/*
 * Copyright (c) 1990,1991,1994 The University of Utah and
 * the Computer Systems Laboratory (CSL).  All rights reserved.
 *
 * Permission to use, copy, modify and distribute this software is hereby
 * granted provided that (1) source code retains these copyright, permission,
 * and disclaimer notices, and (2) redistributions including binaries
 * reproduce the notices in supporting documentation, and (3) all advertising
 * materials mentioning features or use of this software display the following
 * acknowledgement: ``This product includes software developed by the
 * Computer Systems Laboratory at the University of Utah.''
 *
 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
 * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
 * improvements that they make and grant CSL redistribution rights.
 *
 *	Utah $Hdr: asm.h 1.8 94/12/14$
 */

#ifndef _MACHINE_ASM_H_
#define _MACHINE_ASM_H_

/*
 *	hppa assembler definitions
 */

arg7	.reg	%r19
arg6	.reg	%r20
arg5	.reg	%r21
arg4	.reg	%r22
ap	.reg	%r29

#ifdef __STDC__
#define	__CONCAT(a,b)	a ## b
#else
#define	__CONCAT(a,b)	a/**/b
#endif

#ifdef PROF
#define	_PROF_PROLOGUE				\
	stw	%rp, HPPA_FRAME_CRP(%sr0,%sp)	!\
	ldil	L%_mcount,%r1			!\
	ble	R%_mcount(%sr0,%r1)		!\
	ldo	HPPA_FRAME_SIZE(%sp),%sp	!\
	ldw 	PPA_FRAME_CRP(%sr0,%sp),%rp
#else
#define	_PROF_PROLOGUE
#endif

#define	LEAF_ENTRY(x) ! .text ! .align	4	!\
	.export	x, entry ! .label x ! .proc	!\
	.callinfo frame=0,no_calls,save_rp	!\
	.entry ! _PROF_PROLOGUE

#define	ENTRY(x,n) ! .text ! .align 4			!\
	.export	x, entry ! .label x ! .proc		!\
	.callinfo frame=n,calls, save_rp, save_sp	!\
	.entry ! _PROF_PROLOGUE

#define ALTENTRY(x) ! .export x, entry ! .label  x
#define EXIT(x) ! .exit ! .procend ! .size   x, .-x

#define	BSS(n,s)	! .data ! .label n ! .comm s

#define STRONG_ALIAS(alias,sym) ! .global alias ! .set alias, sym
#define WEAK_ALIAS(alias,sym) ! .weak alias ! .set alias, sym

#endif /* _MACHINE_ASM_H_ */


code:
/*	$OpenBSD: atomic.h,v 1.7 2014/10/12 20:39:46 miod Exp $	*/

/* Public Domain */

#ifndef _MACHINE_ATOMIC_H_
#define _MACHINE_ATOMIC_H_

#if defined(_KERNEL)

typedef volatile u_int __cpu_simple_lock_t __attribute__((__aligned__(16)));

#define __SIMPLELOCK_LOCKED	0
#define __SIMPLELOCK_UNLOCKED	1

static inline void
__cpu_simple_lock_init(__cpu_simple_lock_t *l)
{
	*l = __SIMPLELOCK_UNLOCKED;
}

static inline unsigned int
__cpu_simple_lock_ldcws(__cpu_simple_lock_t *l)
{
	unsigned int o;

	asm volatile("ldcws 0(%2), %0" : "=&r" (o), "+m" (l) : "r" (l));

	return (o);
}

static inline void
__cpu_simple_lock(__cpu_simple_lock_t *l)
{
	while (__cpu_simple_lock_ldcws(l) == __SIMPLELOCK_UNLOCKED)
		;
}

static inline int
__cpu_simple_lock_try(__cpu_simple_lock_t *l)
{
	return (__cpu_simple_lock_ldcws(l) == __SIMPLELOCK_UNLOCKED);
}

static inline void
__cpu_simple_unlock(__cpu_simple_lock_t *l)
{
	*l = __SIMPLELOCK_UNLOCKED;
}

#ifdef MULTIPROCESSOR
extern __cpu_simple_lock_t atomic_lock;
#define ATOMIC_LOCK	__cpu_simple_lock(&atomic_lock);
#define ATOMIC_UNLOCK	__cpu_simple_unlock(&atomic_lock);
#else
#define ATOMIC_LOCK
#define ATOMIC_UNLOCK
#endif

static inline register_t
atomic_enter(void)
{
	register_t eiem;

	__asm volatile("mfctl	%%cr15, %0": "=r" (eiem));
	__asm volatile("mtctl	%r0, %cr15");
	ATOMIC_LOCK;

	return (eiem);
}

static inline void
atomic_leave(register_t eiem)
{
	ATOMIC_UNLOCK;
	__asm volatile("mtctl	%0, %%cr15":: "r" (eiem));
}

static inline unsigned int
_atomic_cas_uint(volatile unsigned int *uip, unsigned int o, unsigned int n)
{
	register_t eiem;
	unsigned int rv;

	eiem = atomic_enter();
	rv = *uip;
	if (rv == o)
		*uip = n;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_cas_uint(_p, _o, _n) _atomic_cas_uint((_p), (_o), (_n))

static inline unsigned long
_atomic_cas_ulong(volatile unsigned long *uip, unsigned long o, unsigned long n)
{
	register_t eiem;
	unsigned long rv;

	eiem = atomic_enter();
	rv = *uip;
	if (rv == o)
		*uip = n;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_cas_ulong(_p, _o, _n) _atomic_cas_ulong((_p), (_o), (_n))

static inline void *
_atomic_cas_ptr(volatile void *uip, void *o, void *n)
{
	register_t eiem;
	void * volatile *uipp = (void * volatile *)uip;
	void *rv;

	eiem = atomic_enter();
	rv = *uipp;
	if (rv == o)
		*uipp = n;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_cas_ptr(_p, _o, _n) _atomic_cas_ptr((_p), (_o), (_n))

static inline unsigned int
_atomic_swap_uint(volatile unsigned int *uip, unsigned int n)
{
	register_t eiem;
	unsigned int rv;

	eiem = atomic_enter();
	rv = *uip;
	*uip = n;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_swap_uint(_p, _n) _atomic_swap_uint((_p), (_n))

static inline unsigned long
_atomic_swap_ulong(volatile unsigned long *uip, unsigned long n)
{
	register_t eiem;
	unsigned long rv;

	eiem = atomic_enter();
	rv = *uip;
	*uip = n;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_swap_ulong(_p, _n) _atomic_swap_ulong((_p), (_n))

static inline void *
_atomic_swap_ptr(volatile void *uip, void *n)
{
	register_t eiem;
	void * volatile *uipp = (void * volatile *)uip;
	void *rv;

	eiem = atomic_enter();
	rv = *uipp;
	*uipp = n;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_swap_ptr(_p, _n) _atomic_swap_ptr((_p), (_n))

static __inline unsigned int
_atomic_add_int_nv(volatile unsigned int *uip, unsigned int v)
{
	register_t eiem;
	unsigned int rv;

	eiem = atomic_enter();
	rv = *uip + v;
	*uip = rv;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_add_int_nv(_uip, _v) _atomic_add_int_nv((_uip), (_v))
#define atomic_sub_int_nv(_uip, _v) _atomic_add_int_nv((_uip), 0 - (_v))

static __inline unsigned long
_atomic_add_long_nv(volatile unsigned long *uip, unsigned long v)
{
	register_t eiem;
	unsigned long rv;

	eiem = atomic_enter();
	rv = *uip + v;
	*uip = rv;
	atomic_leave(eiem);

	return (rv);
}
#define atomic_add_long_nv(_uip, _v) _atomic_add_long_nv((_uip), (_v))
#define atomic_sub_long_nv(_uip, _v) _atomic_add_long_nv((_uip), 0 - (_v))

static __inline void
atomic_setbits_int(volatile unsigned int *uip, unsigned int v)
{
	register_t eiem;

	eiem = atomic_enter();
	*uip |= v;
	atomic_leave(eiem);
}

static __inline void
atomic_clearbits_int(volatile unsigned int *uip, unsigned int v)
{
	register_t eiem;

	eiem = atomic_enter();
	*uip &= ~v;
	atomic_leave(eiem);
}

static __inline void
atomic_setbits_long(volatile unsigned long *uip, unsigned long v)
{
	register_t eiem;

	eiem = atomic_enter();
	*uip |= v;
	atomic_leave(eiem);
}

static __inline void
atomic_clearbits_long(volatile unsigned long *uip, unsigned long v)
{
	register_t eiem;

	eiem = atomic_enter();
	*uip &= ~v;
	atomic_leave(eiem);
}

/*
 * Although the PA-RISC 2.0 architecture allows an implementation to
 * be weakly ordered, all PA-RISC processers to date implement a
 * strong memory ordering model.  So all we need is a compiler
 * barrier.
 */

static inline void
__insn_barrier(void)
{
	__asm volatile("" : : : "memory");
}

#define membar_enter()		__insn_barrier()
#define membar_exit()		__insn_barrier()
#define membar_producer()	__insn_barrier()
#define membar_consumer()	__insn_barrier()
#define membar_sync()		__insn_barrier()

#endif /* defined(_KERNEL) */
#endif /* _MACHINE_ATOMIC_H_ */


code:
/*	$OpenBSD: autoconf.h,v 1.3 2011/04/07 13:13:01 jsing Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <machine/bus.h>
#include <machine/pdc.h>

struct confargs {
	const char	*ca_name;	/* device name/description */
	struct iodc_data ca_type;	/* iodc-specific type descrition */
	bus_space_tag_t	ca_iot;		/* io tag */
	bus_dma_tag_t	ca_dmatag;	/* DMA tag */
	hppa_hpa_t	ca_hpa;		/* module HPA */
	u_int		ca_hpasz;	/* module HPA size (if avail) */
	int		ca_mod;		/* this module */
};

/* this is used for hppa_knownmodules table
 * describing known to this port modules,
 * system boards, cpus, fpus and busses
 */
struct hppa_mod_info {
	int	mi_type;
	int	mi_sv;
	const char *mi_name;
};

extern void (*cold_hook)(int);
#define	HPPA_COLD_COLD	0
#define	HPPA_COLD_HOT	1
#define	HPPA_COLD_OFF	2

struct device;

const char *hppa_mod_info(int, int);
void	pdc_scan(struct device *, struct confargs *);
int	mbprint(void *, const char *);

int	cpu_intr_findirq(void);
void	*cpu_intr_map(void *v, int pri, int irq, int (*handler)(void *),
	    void *arg, const char *name);
void	*cpu_intr_establish(int pri, int irq, int (*handler)(void *),
	    void *arg, const char *name);
int	clock_intr(void *);

void	dumpconf(void);


code:
/*	$OpenBSD: bus.h,v 1.6 2011/11/14 14:29:57 deraadt Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _MACHINE_BUS_H_
#define _MACHINE_BUS_H_

/* addresses in bus space */
typedef u_long bus_addr_t;
typedef u_long bus_size_t;

/* access methods for bus space */
typedef u_long bus_space_handle_t;

struct hppa64_bus_space_tag {
	void *hbt_cookie;

	int  (*hbt_map)(void *v, bus_addr_t addr, bus_size_t size,
		    int flags, bus_space_handle_t *bshp);
	void (*hbt_unmap)(void *v, bus_space_handle_t bsh, bus_size_t size);
	int  (*hbt_subregion)(void *v, bus_space_handle_t bsh,
		    bus_size_t offset, bus_size_t size,
		    bus_space_handle_t *nbshp);
	int  (*hbt_alloc)(void *v, 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);
	void (*hbt_free)(void *, bus_space_handle_t, bus_size_t);
	void (*hbt_barrier)(void *v, bus_space_handle_t h,
		    bus_size_t o, bus_size_t l, int op);
	void *(*hbt_vaddr)(void *v, bus_space_handle_t h);

	u_int8_t  (*hbt_r1)(void *, bus_space_handle_t, bus_size_t);
	u_int16_t (*hbt_r2)(void *, bus_space_handle_t, bus_size_t);
	u_int32_t (*hbt_r4)(void *, bus_space_handle_t, bus_size_t);
	u_int64_t (*hbt_r8)(void *, bus_space_handle_t, bus_size_t);

	void (*hbt_w1)(void *, bus_space_handle_t, bus_size_t, u_int8_t);
	void (*hbt_w2)(void *, bus_space_handle_t, bus_size_t, u_int16_t);
	void (*hbt_w4)(void *, bus_space_handle_t, bus_size_t, u_int32_t);
	void (*hbt_w8)(void *, bus_space_handle_t, bus_size_t, u_int64_t);

	void (*hbt_rm_1)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int8_t *a, bus_size_t c);
	void (*hbt_rm_2)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int16_t *a, bus_size_t c);
	void (*hbt_rm_4)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int32_t *a, bus_size_t c);
	void (*hbt_rm_8)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int64_t *a, bus_size_t c);

	void (*hbt_wm_1)(void *v, bus_space_handle_t h, bus_size_t o,
	      const u_int8_t *a, bus_size_t c);
	void (*hbt_wm_2)(void *v, bus_space_handle_t h, bus_size_t o,
	      const u_int16_t *a, bus_size_t c);
	void (*hbt_wm_4)(void *v, bus_space_handle_t h, bus_size_t o,
	      const u_int32_t *a, bus_size_t c);
	void (*hbt_wm_8)(void *v, bus_space_handle_t h, bus_size_t o,
	      const u_int64_t *a, bus_size_t c);

	void (*hbt_sm_1)(void *v, bus_space_handle_t h, bus_size_t o,
	      u_int8_t  vv, bus_size_t c);
	void (*hbt_sm_2)(void *v, bus_space_handle_t h, bus_size_t o,
	      u_int16_t vv, bus_size_t c);
	void (*hbt_sm_4)(void *v, bus_space_handle_t h, bus_size_t o,
	      u_int32_t vv, bus_size_t c);
	void (*hbt_sm_8)(void *v, bus_space_handle_t h, bus_size_t o,
	      u_int64_t vv, bus_size_t c);

	void (*hbt_rrm_2)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t *a, bus_size_t c);
	void (*hbt_rrm_4)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t *a, bus_size_t c);
	void (*hbt_rrm_8)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t *a, bus_size_t c);

	void (*hbt_wrm_2)(void *v, bus_space_handle_t h,
	       bus_size_t o, const u_int8_t *a, bus_size_t c);
	void (*hbt_wrm_4)(void *v, bus_space_handle_t h,
	       bus_size_t o, const u_int8_t *a, bus_size_t c);
	void (*hbt_wrm_8)(void *v, bus_space_handle_t h,
	       bus_size_t o, const u_int8_t *a, bus_size_t c);

	void (*hbt_rr_1)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int8_t *a, bus_size_t c);
	void (*hbt_rr_2)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int16_t *a, bus_size_t c);
	void (*hbt_rr_4)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int32_t *a, bus_size_t c);
	void (*hbt_rr_8)(void *v, bus_space_handle_t h,
	      bus_size_t o, u_int64_t *a, bus_size_t c);

	void (*hbt_wr_1)(void *v, bus_space_handle_t h,
	      bus_size_t o, const u_int8_t *a, bus_size_t c);
	void (*hbt_wr_2)(void *v, bus_space_handle_t h,
	      bus_size_t o, const u_int16_t *a, bus_size_t c);
	void (*hbt_wr_4)(void *v, bus_space_handle_t h,
	      bus_size_t o, const u_int32_t *a, bus_size_t c);
	void (*hbt_wr_8)(void *v, bus_space_handle_t h,
	      bus_size_t o, const u_int64_t *a, bus_size_t c);

	void (*hbt_rrr_2)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t *a, bus_size_t c);
	void (*hbt_rrr_4)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t *a, bus_size_t c);
	void (*hbt_rrr_8)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t *a, bus_size_t c);

	void (*hbt_wrr_2)(void *v, bus_space_handle_t h,
	       bus_size_t o, const u_int8_t *a, bus_size_t c);
	void (*hbt_wrr_4)(void *v, bus_space_handle_t h,
	       bus_size_t o, const u_int8_t *a, bus_size_t c);
	void (*hbt_wrr_8)(void *v, bus_space_handle_t h,
	       bus_size_t o, const u_int8_t *a, bus_size_t c);

	void (*hbt_sr_1)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int8_t vv, bus_size_t c);
	void (*hbt_sr_2)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int16_t vv, bus_size_t c);
	void (*hbt_sr_4)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int32_t vv, bus_size_t c);
	void (*hbt_sr_8)(void *v, bus_space_handle_t h,
	       bus_size_t o, u_int64_t vv, bus_size_t c);

	void (*hbt_cp_1)(void *v, bus_space_handle_t h1, bus_size_t o1,
	      bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
	void (*hbt_cp_2)(void *v, bus_space_handle_t h1, bus_size_t o1,
	      bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
	void (*hbt_cp_4)(void *v, bus_space_handle_t h1, bus_size_t o1,
	      bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
	void (*hbt_cp_8)(void *v, bus_space_handle_t h1, bus_size_t o1,
	      bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
};
typedef struct hppa64_bus_space_tag *bus_space_tag_t;

/* flags for bus space map functions */
#define	BUS_SPACE_MAP_CACHEABLE		0x0001
#define	BUS_SPACE_MAP_LINEAR		0x0002
#define	BUS_SPACE_MAP_READONLY		0x0004
#define	BUS_SPACE_MAP_PREFETCHABLE	0x0008

/* bus access routines */

#define	bus_space_map(t,a,c,ca,hp) \
	(((t)->hbt_map)((t)->hbt_cookie,(a),(c),(ca),(hp)))
#define	bus_space_unmap(t,h,c) \
	(((t)->hbt_unmap)((t)->hbt_cookie,(h),(c)))
#define	bus_space_subregion(t,h,o,c,hp) \
	(((t)->hbt_subregion)((t)->hbt_cookie,(h),(o),(c),(hp)))
#define	bus_space_alloc(t,b,e,c,al,bn,ca,ap,hp) \
	(((t)->hbt_alloc)((t)->hbt_cookie,(b),(e),(c),(al),(bn),(ca),(ap),(hp)))
#define	bus_space_free(t,h,c) \
	(((t)->hbt_free)((t)->hbt_cookie,(h),(c)))

#define	bus_space_read_1(t,h,o) (((t)->hbt_r1)((t)->hbt_cookie,(h),(o)))
#define	bus_space_read_2(t,h,o) (((t)->hbt_r2)((t)->hbt_cookie,(h),(o)))
#define	bus_space_read_4(t,h,o) (((t)->hbt_r4)((t)->hbt_cookie,(h),(o)))
#define	bus_space_read_8(t,h,o) (((t)->hbt_r8)((t)->hbt_cookie,(h),(o)))

#define	bus_space_write_1(t,h,o,v) (((t)->hbt_w1)((t)->hbt_cookie,(h),(o),(v)))
#define	bus_space_write_2(t,h,o,v) (((t)->hbt_w2)((t)->hbt_cookie,(h),(o),(v)))
#define	bus_space_write_4(t,h,o,v) (((t)->hbt_w4)((t)->hbt_cookie,(h),(o),(v)))
#define	bus_space_write_8(t,h,o,v) (((t)->hbt_w8)((t)->hbt_cookie,(h),(o),(v)))

#define	bus_space_read_multi_1(t,h,o,a,c) \
	(((t)->hbt_rm_1)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_multi_2(t,h,o,a,c) \
	(((t)->hbt_rm_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_multi_4(t,h,o,a,c) \
	(((t)->hbt_rm_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_multi_8(t,h,o,a,c) \
	(((t)->hbt_rm_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_write_multi_1(t,h,o,a,c) \
	(((t)->hbt_wm_1)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_multi_2(t,h,o,a,c) \
	(((t)->hbt_wm_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_multi_4(t,h,o,a,c) \
	(((t)->hbt_wm_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_multi_8(t,h,o,a,c) \
	(((t)->hbt_wm_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_set_multi_1(t,h,o,v,c) \
	(((t)->hbt_sm_1)((t)->hbt_cookie, (h), (o), (v), (c)))
#define	bus_space_set_multi_2(t,h,o,v,c) \
	(((t)->hbt_sm_2)((t)->hbt_cookie, (h), (o), (v), (c)))
#define	bus_space_set_multi_4(t,h,o,v,c) \
	(((t)->hbt_sm_4)((t)->hbt_cookie, (h), (o), (v), (c)))
#define	bus_space_set_multi_8(t,h,o,v,c) \
	(((t)->hbt_sm_8)((t)->hbt_cookie, (h), (o), (v), (c)))

#define	bus_space_read_raw_multi_2(t, h, o, a, c) \
	(((t)->hbt_rrm_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_raw_multi_4(t, h, o, a, c) \
	(((t)->hbt_rrm_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_raw_multi_8(t, h, o, a, c) \
	(((t)->hbt_rrm_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_write_raw_multi_2(t, h, o, a, c) \
	(((t)->hbt_wrm_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_raw_multi_4(t, h, o, a, c) \
	(((t)->hbt_wrm_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_raw_multi_8(t, h, o, a, c) \
	(((t)->hbt_wrm_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_read_region_1(t, h, o, a, c) \
	(((t)->hbt_rr_1)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_region_2(t, h, o, a, c) \
	(((t)->hbt_rr_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_region_4(t, h, o, a, c) \
	(((t)->hbt_rr_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_region_8(t, h, o, a, c) \
	(((t)->hbt_rr_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_write_region_1(t, h, o, a, c) \
	(((t)->hbt_wr_1)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_region_2(t, h, o, a, c) \
	(((t)->hbt_wr_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_region_4(t, h, o, a, c) \
	(((t)->hbt_wr_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_region_8(t, h, o, a, c) \
	(((t)->hbt_wr_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_read_raw_region_2(t, h, o, a, c) \
	(((t)->hbt_rrr_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_raw_region_4(t, h, o, a, c) \
	(((t)->hbt_rrr_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_read_raw_region_8(t, h, o, a, c) \
	(((t)->hbt_rrr_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_write_raw_region_2(t, h, o, a, c) \
	(((t)->hbt_wrr_2)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_raw_region_4(t, h, o, a, c) \
	(((t)->hbt_wrr_4)((t)->hbt_cookie, (h), (o), (a), (c)))
#define	bus_space_write_raw_region_8(t, h, o, a, c) \
	(((t)->hbt_wrr_8)((t)->hbt_cookie, (h), (o), (a), (c)))

#define	bus_space_set_region_1(t, h, o, v, c) \
	(((t)->hbt_sr_1)((t)->hbt_cookie, (h), (o), (v), (c)))
#define	bus_space_set_region_2(t, h, o, v, c) \
	(((t)->hbt_sr_2)((t)->hbt_cookie, (h), (o), (v), (c)))
#define	bus_space_set_region_4(t, h, o, v, c) \
	(((t)->hbt_sr_4)((t)->hbt_cookie, (h), (o), (v), (c)))
#define	bus_space_set_region_8(t, h, o, v, c) \
	(((t)->hbt_sr_8)((t)->hbt_cookie, (h), (o), (v), (c)))

#define	bus_space_copy_1(t, h1, o1, h2, o2, c) \
	(((t)->hbt_cp_1)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c)))
#define	bus_space_copy_2(t, h1, o1, h2, o2, c) \
	(((t)->hbt_cp_2)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c)))
#define	bus_space_copy_4(t, h1, o1, h2, o2, c) \
	(((t)->hbt_cp_4)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c)))
#define	bus_space_copy_8(t, h1, o1, h2, o2, c) \
	(((t)->hbt_cp_8)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c)))

#define	BUS_SPACE_BARRIER_READ	0x01
#define	BUS_SPACE_BARRIER_WRITE	0x02

#define	bus_space_barrier(t,h,o,l,op) \
	((t)->hbt_barrier((t)->hbt_cookie, (h), (o), (l), (op)))
#define	bus_space_vaddr(t,h) \
	((t)->hbt_vaddr((t)->hbt_cookie, (h)))

#define	BUS_DMA_WAITOK		0x0000	/* safe to sleep (pseudo-flag) */
#define	BUS_DMA_NOWAIT		0x0001	/* not safe to sleep */
#define	BUS_DMA_ALLOCNOW	0x0002	/* perform resource allocation now */
#define	BUS_DMA_COHERENT	0x0004	/* hint: map memory DMA coherent */
#define	BUS_DMA_BUS1		0x0020	/* placeholders for bus functions... */
#define	BUS_DMA_BUS2		0x0040
#define	BUS_DMA_BUS3		0x0080
#define	BUS_DMA_BUS4		0x0100
#define	BUS_DMA_STREAMING	0x0200	/* hint: sequential, unidirectional */
#define	BUS_DMA_READ		0x0400	/* mapping is device -> memory only */
#define	BUS_DMA_WRITE		0x0800	/* mapping is memory -> device only */
#define	BUS_DMA_ZERO		0x1000	/* zero memory in dmamem_alloc */

/* Forwards needed by prototypes below. */
struct mbuf;
struct proc;
struct uio;

/* Operations performed by bus_dmamap_sync().  */
#define BUS_DMASYNC_POSTREAD	0x01
#define BUS_DMASYNC_POSTWRITE	0x02
#define BUS_DMASYNC_PREREAD	0x04
#define BUS_DMASYNC_PREWRITE	0x08

typedef const struct hppa64_bus_dma_tag	*bus_dma_tag_t;
typedef struct hppa64_bus_dmamap	*bus_dmamap_t;

/*
 *	bus_dma_segment_t
 *
 *	Describes a single contiguous DMA transaction.  Values
 *	are suitable for programming into DMA registers.
 */
struct hppa64_bus_dma_segment {
	vaddr_t		_ds_va;		/* needed for syncing */

	bus_addr_t	ds_addr;	/* DMA address */
	bus_size_t	ds_len;		/* length of transfer */
};
typedef struct hppa64_bus_dma_segment	bus_dma_segment_t;

/*
 *	bus_dma_tag_t
 *
 *	A machine-dependent opaque type describing the implementation of
 *	DMA for a given bus.
 */

struct hppa64_bus_dma_tag {
	void	*_cookie;		/* cookie used in the guts */

	/*
	 * DMA mapping methods.
	 */
	int	(*_dmamap_create)(void *, bus_size_t, int,
		    bus_size_t, bus_size_t, int, bus_dmamap_t *);
	void	(*_dmamap_destroy)(void *, bus_dmamap_t);
	int	(*_dmamap_load)(void *, bus_dmamap_t, void *,
		    bus_size_t, struct proc *, int);
	int	(*_dmamap_load_mbuf)(void *, bus_dmamap_t,
		    struct mbuf *, int);
	int	(*_dmamap_load_uio)(void *, bus_dmamap_t,
		    struct uio *, int);
	int	(*_dmamap_load_raw)(void *, bus_dmamap_t,
		    bus_dma_segment_t *, int, bus_size_t, int);
	void	(*_dmamap_unload)(void *, bus_dmamap_t);
	void	(*_dmamap_sync)(void *, bus_dmamap_t, bus_addr_t,
		    bus_size_t, int);

	/*
	 * DMA memory utility functions.
	 */
	int	(*_dmamem_alloc)(void *, bus_size_t, bus_size_t,
		    bus_size_t, bus_dma_segment_t *, int, int *, int);
	void	(*_dmamem_free)(void *, bus_dma_segment_t *, int);
	int	(*_dmamem_map)(void *, bus_dma_segment_t *,
		    int, size_t, caddr_t *, int);
	void	(*_dmamem_unmap)(void *, caddr_t, size_t);
	paddr_t	(*_dmamem_mmap)(void *, bus_dma_segment_t *,
		    int, off_t, int, int);
};

#define	bus_dmamap_create(t, s, n, m, b, f, p)			\
	(*(t)->_dmamap_create)((t)->_cookie, (s), (n), (m), (b), (f), (p))
#define	bus_dmamap_destroy(t, p)				\
	(*(t)->_dmamap_destroy)((t)->_cookie, (p))
#define	bus_dmamap_load(t, m, b, s, p, f)			\
	(*(t)->_dmamap_load)((t)->_cookie, (m), (b), (s), (p), (f))
#define	bus_dmamap_load_mbuf(t, m, b, f)			\
	(*(t)->_dmamap_load_mbuf)((t)->_cookie, (m), (b), (f))
#define	bus_dmamap_load_uio(t, m, u, f)				\
	(*(t)->_dmamap_load_uio)((t)->_cookie, (m), (u), (f))
#define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
	(*(t)->_dmamap_load_raw)((t)->_cookie, (m), (sg), (n), (s), (f))
#define	bus_dmamap_unload(t, p)					\
	(*(t)->_dmamap_unload)((t)->_cookie, (p))
#define	bus_dmamap_sync(t, p, a, l, o)				\
	(void)((t)->_dmamap_sync ?				\
	    (*(t)->_dmamap_sync)((t)->_cookie, (p), (a), (l), (o)) : (void)0)

#define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
	(*(t)->_dmamem_alloc)((t)->_cookie, (s), (a), (b), (sg), (n), (r), (f))
#define	bus_dmamem_free(t, sg, n)				\
	(*(t)->_dmamem_free)((t)->_cookie, (sg), (n))
#define	bus_dmamem_map(t, sg, n, s, k, f)			\
	(*(t)->_dmamem_map)((t)->_cookie, (sg), (n), (s), (k), (f))
#define	bus_dmamem_unmap(t, k, s)				\
	(*(t)->_dmamem_unmap)((t)->_cookie, (k), (s))
#define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
	(*(t)->_dmamem_mmap)((t)->_cookie, (sg), (n), (o), (p), (f))

/*
 *	bus_dmamap_t
 *
 *	Describes a DMA mapping.
 */
struct hppa64_bus_dmamap {
	/*
	 * PRIVATE MEMBERS: not for use by machine-independent code.
	 */
	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
	int		_dm_segcnt;	/* number of segs this map can map */
	bus_size_t	_dm_maxsegsz;	/* largest possible segment */
	bus_size_t	_dm_boundary;	/* don't cross this */
	int		_dm_flags;	/* misc. flags */

	void		*_dm_cookie;	/* cookie for bus-specific functions */

	/*
	 * PUBLIC MEMBERS: these are used by machine-independent code.
	 */
	bus_size_t	dm_mapsize;	/* size of the mapping */
	int		dm_nsegs;	/* # valid segments in mapping */
	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
};

#endif /* _MACHINE_BUS_H_ */


code:
/*	$OpenBSD: cdefs.h,v 1.3 2013/03/28 17:30:45 martynas 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.
 */

#ifndef _MACHINE_CDEFS_H_
#define	_MACHINE_CDEFS_H_

#define	__strong_alias(alias,sym)					\
	__asm__(".export " __STRING(alias) ", entry\n\t.global "	\
	    __STRING(alias) "\n\t" __STRING(alias) " = " __STRING(sym))
#define	__weak_alias(alias,sym)						\
	__asm__(".export " __STRING(alias) ", entry\n\t.weak "		\
	    __STRING(alias) "\n\t" __STRING(alias) " = " __STRING(sym))
#define	__warn_references(sym,msg)					\
	__asm__(".section .gnu.warning." __STRING(sym)			\
	    "\n\t.ascii \"" msg "\"\n\t.text")

#endif /* !_MACHINE_CDEFS_H_ */


code:
/*	$OpenBSD: conf.h,v 1.2 2011/11/14 14:29:57 deraadt Exp $	*/

/*
 * Copyright (c) 1998-2005 Michael Shalayeff
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _MACHINE_CONF_H_
#define _MACHINE_CONF_H_

#include <sys/conf.h>
struct tty;
struct termios;

cdev_decl(pdc);
int pdcparam(struct tty *, struct termios *);
void pdcstart(struct tty *);

#define mmread  mmrw
#define mmwrite mmrw
cdev_decl(mm);

cdev_decl(fd);
bdev_decl(fd);

#endif /* _MACHINE_CONF_H_ */