code:
/*	$OpenBSD: bus.h,v 1.32 2015/01/24 15:13:55 kettenis Exp $	*/
/*	$NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $	*/

/*-
 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
 * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Christopher G. Demetriou
 *	for the NetBSD Project.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _MACHINE_BUS_H_
#define _MACHINE_BUS_H_

#include <sys/mutex.h>
#include <sys/tree.h>

#include <machine/pio.h>

/*
 * Bus address and size types
 */
typedef u_long bus_addr_t;
typedef u_long bus_size_t;

/*
 * Access methods for bus resources and address space.
 */
struct x86_bus_space_ops;
typedef	const struct x86_bus_space_ops *bus_space_tag_t;
typedef	u_long bus_space_handle_t;

int	bus_space_map(bus_space_tag_t t, bus_addr_t addr,
    bus_size_t size, int flags, bus_space_handle_t *bshp);
/* like map, but without extent map checking/allocation */
int	_bus_space_map(bus_space_tag_t t, bus_addr_t addr,
    bus_size_t size, int flags, bus_space_handle_t *bshp);

int	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
	    bus_addr_t rend, bus_size_t size, bus_size_t align,
	    bus_size_t boundary, int flags, bus_addr_t *addrp,
	    bus_space_handle_t *bshp);
void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
	    bus_size_t size);

/*
 *      int bus_space_unmap(bus_space_tag_t t,
 *          bus_space_handle_t bsh, bus_size_t size);
 *
 * Unmap a region of bus space.
 */

void	bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
	    bus_size_t size);
void	_bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
	    bus_size_t size, bus_addr_t *);

/* like bus_space_map(), but without extent map checking/allocation */
int	_bus_space_map(bus_space_tag_t t, bus_addr_t addr,
	    bus_size_t size, int flags, bus_space_handle_t *bshp);

/*
 *      int bus_space_subregion(bus_space_tag_t t,
 *          bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
 *          bus_space_handle_t *nbshp);
 *
 * Get a new handle for a subregion of an already-mapped area of bus space.
 */

int	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
	    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);

struct x86_bus_space_ops {

/*
 *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset);
 *
 * Read a 1, 2, 4, or 8 byte quantity from bus space
 * described by tag/handle/offset.
 */
	u_int8_t	(*read_1)(bus_space_handle_t, bus_size_t);
	u_int16_t	(*read_2)(bus_space_handle_t, bus_size_t);
	u_int32_t	(*read_4)(bus_space_handle_t, bus_size_t);
	u_int64_t	(*read_8)(bus_space_handle_t, bus_size_t);

#define bus_space_read_1(_t, _h, _o) ((_t)->read_1((_h), (_o)))
#define bus_space_read_2(_t, _h, _o) ((_t)->read_2((_h), (_o)))
#define bus_space_read_4(_t, _h, _o) ((_t)->read_4((_h), (_o)))
#define bus_space_read_8(_t, _h, _o) ((_t)->read_8((_h), (_o)))

#define bus_space_read_raw_2(_t, _h, _o) ((_t)->read_2((_h), (_o)))
#define bus_space_read_raw_4(_t, _h, _o) ((_t)->read_4((_h), (_o)))
#define bus_space_read_raw_8(_t, _h, _o) ((_t)->read_8((_h), (_o)))

/*
 *	void bus_space_read_multi_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_intN_t *addr, size_t count);
 *
 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
 * described by tag/handle/offset and copy into buffer provided.
 */

	void		(*read_multi_1)(bus_space_handle_t, bus_size_t,
			    u_int8_t *, bus_size_t);
	void		(*read_multi_2)(bus_space_handle_t, bus_size_t,
			    u_int16_t *, bus_size_t);
	void		(*read_multi_4)(bus_space_handle_t, bus_size_t,
			    u_int32_t *, bus_size_t);
	void		(*read_multi_8)(bus_space_handle_t, bus_size_t,
			    u_int64_t *, bus_size_t);

#define bus_space_read_multi_1(_t, _h, _o, _a, _c) \
	((_t)->read_multi_1((_h), (_o), (_a), (_c)))
#define bus_space_read_multi_2(_t, _h, _o, _a, _c) \
	((_t)->read_multi_2((_h), (_o), (_a), (_c)))
#define bus_space_read_multi_4(_t, _h, _o, _a, _c) \
	((_t)->read_multi_4((_h), (_o), (_a), (_c)))
#define bus_space_read_multi_8(_t, _h, _o, _a, _c) \
	((_t)->read_multi_8((_h), (_o), (_a), (_c)))

/*
 *	void bus_space_read_raw_multi_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_int8_t *addr, size_t count);
 *
 * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
 * described by tag/handle/offset and copy into buffer provided.  The buffer
 * must have proper alignment for the N byte wide entities.  Furthermore
 * possible byte-swapping should be done by these functions.
 */

#define bus_space_read_raw_multi_2(_t, _h, _o, _a, _c) \
	((_t)->read_multi_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1))
#define bus_space_read_raw_multi_4(_t, _h, _o, _a, _c) \
	((_t)->read_multi_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2))
#define bus_space_read_raw_multi_8(_t, _h, _o, _a, _c) \
	((_t)->read_multi_8((_h), (_o), (u_int64_t *)(_a), (_c) >> 3))

/*
 *	void bus_space_read_region_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_intN_t *addr, size_t count);
 *
 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
 * described by tag/handle and starting at `offset' and copy into
 * buffer provided.
 */

	void		(*read_region_1)(bus_space_handle_t,
			    bus_size_t, u_int8_t *, bus_size_t);
	void		(*read_region_2)(bus_space_handle_t,
			    bus_size_t, u_int16_t *, bus_size_t);
	void		(*read_region_4)(bus_space_handle_t,
			    bus_size_t, u_int32_t *, bus_size_t);
	void		(*read_region_8)(bus_space_handle_t,
			    bus_size_t, u_int64_t *, bus_size_t);

#define bus_space_read_region_1(_t, _h, _o, _a, _c) \
	((_t)->read_region_1((_h), (_o), (_a), (_c)))
#define bus_space_read_region_2(_t, _h, _o, _a, _c) \
	((_t)->read_region_2((_h), (_o), (_a), (_c)))
#define bus_space_read_region_4(_t, _h, _o, _a, _c) \
	((_t)->read_region_4((_h), (_o), (_a), (_c)))
#define bus_space_read_region_8(_t, _h, _o, _a, _c) \
	((_t)->read_region_8((_h), (_o), (_a), (_c)))

/*
 *	void bus_space_read_raw_region_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_int8_t *addr, size_t count);
 *
 * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
 * described by tag/handle and starting at `offset' and copy into
 * buffer provided.  The buffer must have proper alignment for the N byte
 * wide entities.  Furthermore possible byte-swapping should be done by
 * these functions.
 */

#define bus_space_read_raw_region_2(_t, _h, _o, _a, _c) \
	((_t)->read_region_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1))
#define bus_space_read_raw_region_4(_t, _h, _o, _a, _c) \
	((_t)->read_region_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2))
#define bus_space_read_raw_region_8(_t, _h, _o, _a, _c) \
	((_t)->read_region_8((_h), (_o), (u_int64_t *)(_a), (_c) >> 3))

/*
 *	void bus_space_write_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_intN_t value);
 *
 * Write the 1, 2, 4, or 8 byte value `value' to bus space
 * described by tag/handle/offset.
 */

	void		(*write_1)(bus_space_handle_t, bus_size_t, u_int8_t);
	void		(*write_2)(bus_space_handle_t, bus_size_t, u_int16_t);
	void		(*write_4)(bus_space_handle_t, bus_size_t, u_int32_t);
	void		(*write_8)(bus_space_handle_t, bus_size_t, u_int64_t);

#define bus_space_write_1(_t, _h, _o, _v) \
	((_t)->write_1((_h), (_o), (_v)))
#define bus_space_write_2(_t, _h, _o, _v) \
	((_t)->write_2((_h), (_o), (_v)))
#define bus_space_write_4(_t, _h, _o, _v) \
	((_t)->write_4((_h), (_o), (_v)))
#define bus_space_write_8(_t, _h, _o, _v) \
	((_t)->write_8((_h), (_o), (_v)))

#define bus_space_write_raw_2(_t, _h, _o, _v) \
	((_t)->write_2((_h), (_o), (_v)))
#define bus_space_write_raw_4(_t, _h, _o, _v) \
	((_t)->write_4((_h), (_o), (_v)))
#define bus_space_write_raw_8(_t, _h, _o, _v) \
	((_t)->write_8((_h), (_o), (_v)))

/*
 *	void bus_space_write_multi_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    const u_intN_t *addr, size_t count);
 *
 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
 * provided to bus space described by tag/handle/offset.
 */

	void		(*write_multi_1)(bus_space_handle_t,
			    bus_size_t, const u_int8_t *, bus_size_t);
	void		(*write_multi_2)(bus_space_handle_t,
			    bus_size_t, const u_int16_t *, bus_size_t);
	void		(*write_multi_4)(bus_space_handle_t,
			    bus_size_t, const u_int32_t *, bus_size_t);
	void		(*write_multi_8)(bus_space_handle_t,
			    bus_size_t, const u_int64_t *, bus_size_t);

#define bus_space_write_multi_1(_t, _h, _o, _a, _c) \
	((_t)->write_multi_1((_h), (_o), (_a), (_c)))
#define bus_space_write_multi_2(_t, _h, _o, _a, _c) \
	((_t)->write_multi_2((_h), (_o), (_a), (_c)))
#define bus_space_write_multi_4(_t, _h, _o, _a, _c) \
	((_t)->write_multi_4((_h), (_o), (_a), (_c)))
#define bus_space_write_multi_8(_t, _h, _o, _a, _c) \
	((_t)->write_multi_8((_h), (_o), (_a), (_c)))

/*
 *	void bus_space_write_raw_multi_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    const u_int8_t *addr, size_t count);
 *
 * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
 * provided to bus space described by tag/handle/offset.  The buffer
 * must have proper alignment for the N byte wide entities.  Furthermore
 * possible byte-swapping should be done by these functions.
 */

#define bus_space_write_raw_multi_2(_t, _h, _o, _a, _c) \
	((_t)->write_multi_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1))
#define bus_space_write_raw_multi_4(_t, _h, _o, _a, _c) \
	((_t)->write_multi_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2))
#define bus_space_write_raw_multi_8(_t, _h, _o, _a, _c) \
	((_t)->write_multi_8((_h), (_o), (const u_int64_t *)(_a), (_c) >> 3))

/*
 *	void bus_space_write_region_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    const u_intN_t *addr, size_t count);
 *
 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
 * to bus space described by tag/handle starting at `offset'.
 */

	void		(*write_region_1)(bus_space_handle_t,
			    bus_size_t, const u_int8_t *, bus_size_t);
	void		(*write_region_2)(bus_space_handle_t,
			    bus_size_t, const u_int16_t *, bus_size_t);
	void		(*write_region_4)(bus_space_handle_t,
			    bus_size_t, const u_int32_t *, bus_size_t);
	void		(*write_region_8)(bus_space_handle_t,
			    bus_size_t, const u_int64_t *, bus_size_t);

#define bus_space_write_region_1(_t, _h, _o, _a, _c) \
	((_t)->write_region_1((_h), (_o), (_a), (_c)))
#define bus_space_write_region_2(_t, _h, _o, _a, _c) \
	((_t)->write_region_2((_h), (_o), (_a), (_c)))
#define bus_space_write_region_4(_t, _h, _o, _a, _c) \
	((_t)->write_region_4((_h), (_o), (_a), (_c)))
#define bus_space_write_region_8(_t, _h, _o, _a, _c) \
	((_t)->write_region_8((_h), (_o), (_a), (_c)))

/*
 *	void bus_space_write_raw_region_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    const u_int8_t *addr, size_t count);
 *
 * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
 * described by tag/handle and starting at `offset' from the
 * buffer provided.  The buffer must have proper alignment for the N byte
 * wide entities.  Furthermore possible byte-swapping should be done by
 * these functions.
 */

#define bus_space_write_raw_region_2(_t, _h, _o, _a, _c) \
	((_t)->write_region_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1))
#define bus_space_write_raw_region_4(_t, _h, _o, _a, _c) \
	((_t)->write_region_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2))
#define bus_space_write_raw_region_8(_t, _h, _o, _a, _c) \
	((_t)->write_region_8((_h), (_o), (const u_int64_t *)(_a), (_c) >> 3))

/*
 *	void bus_space_set_multi_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_intN_t val, size_t count);
 *
 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
 * by tag/handle/offset `count' times.
 */

	void		(*set_multi_1)(bus_space_handle_t,
			    bus_size_t, u_int8_t, size_t);
	void		(*set_multi_2)(bus_space_handle_t,
			    bus_size_t, u_int16_t, size_t);
	void		(*set_multi_4)(bus_space_handle_t,
			    bus_size_t, u_int32_t, size_t);
	void		(*set_multi_8)(bus_space_handle_t,
			    bus_size_t, u_int64_t, size_t);

#define bus_space_set_multi_1(_t, _h, _o, _a, _c) \
	((_t)->set_multi_1((_h), (_o), (_a), (_c)))
#define bus_space_set_multi_2(_t, _h, _o, _a, _c) \
	((_t)->set_multi_2((_h), (_o), (_a), (_c)))
#define bus_space_set_multi_4(_t, _h, _o, _a, _c) \
	((_t)->set_multi_4((_h), (_o), (_a), (_c)))
#define bus_space_set_multi_8(_t, _h, _o, _a, _c) \
	((_t)->set_multi_8((_h), (_o), (_a), (_c)))

/*
 *	void bus_space_set_region_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh, bus_size_t offset,
 *	    u_intN_t val, size_t count);
 *
 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
 * by tag/handle starting at `offset'.
 */

	void		(*set_region_1)(bus_space_handle_t,
			    bus_size_t, u_int8_t, size_t);
	void		(*set_region_2)(bus_space_handle_t,
			    bus_size_t, u_int16_t, size_t);
	void		(*set_region_4)(bus_space_handle_t,
			    bus_size_t, u_int32_t, size_t);
	void		(*set_region_8)(bus_space_handle_t,
			    bus_size_t, u_int64_t, size_t);

#define bus_space_set_region_1(_t, _h, _o, _a, _c) \
	((_t)->set_region_1((_h), (_o), (_a), (_c)))
#define bus_space_set_region_2(_t, _h, _o, _a, _c) \
	((_t)->set_region_2((_h), (_o), (_a), (_c)))
#define bus_space_set_region_4(_t, _h, _o, _a, _c) \
	((_t)->set_region_4((_h), (_o), (_a), (_c)))
#define bus_space_set_region_8(_t, _h, _o, _a, _c) \
	((_t)->set_region_8((_h), (_o), (_a), (_c)))

/*
 *	void bus_space_copy_N(bus_space_tag_t tag,
 *	    bus_space_handle_t bsh1, bus_size_t off1,
 *	    bus_space_handle_t bsh2, bus_size_t off2,
 *	    size_t count);
 *
 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
 */

	void		(*copy_1)(bus_space_handle_t,
			    bus_size_t, bus_space_handle_t, bus_size_t, size_t);
	void		(*copy_2)(bus_space_handle_t,
			    bus_size_t, bus_space_handle_t, bus_size_t, size_t);
	void		(*copy_4)(bus_space_handle_t,
			    bus_size_t, bus_space_handle_t, bus_size_t, size_t);
	void		(*copy_8)(bus_space_handle_t,
			    bus_size_t, bus_space_handle_t, bus_size_t, size_t);

#define bus_space_copy_1(_t, _h1, _o1, _h2, _o2, _c) \
	((_t)->copy_1((_h1), (_o1), (_h2), (_o2), (_c)))
#define bus_space_copy_2(_t, _h1, _o1, _h2, _o2, _c) \
	((_t)->copy_2((_h1), (_o1), (_h2), (_o2), (_c)))
#define bus_space_copy_4(_t, _h1, _o1, _h2, _o2, _c) \
	((_t)->copy_4((_h1), (_o1), (_h2), (_o2), (_c)))
#define bus_space_copy_8(_t, _h1, _o1, _h2, _o2, _c) \
	((_t)->copy_8((_h1), (_o1), (_h2), (_o2), (_c)))

/*
 *	void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
 *
 * Get the kernel virtual address for the mapped bus space.
 * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
 */
	void *		(*vaddr)(bus_space_handle_t);

#define bus_space_vaddr(_t, _h) \
	((_t)->vaddr((_h)))

/*
 *      paddr_t bus_space_mmap(bus_space_tag_t t, bus_addr_t base,
 *          off_t offset, int prot, int flags);
 *
 * Mmap an area of bus space.
 */

	paddr_t		(*mmap)(bus_addr_t, off_t, int, int);

#define bus_space_mmap(_t, _a, _o, _p, _f) \
	((_t)->mmap((_a), (_o), (_p), (_f)))
};

/*
 * Bus read/write barrier methods.
 */
#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */

static inline void
bus_space_barrier(bus_space_tag_t space, bus_space_handle_t
    handle, bus_size_t offset, bus_size_t length, int flags)
{
	switch (flags) {
	case (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE):
		__asm volatile("mfence");
		break;
	case BUS_SPACE_BARRIER_WRITE:
		__asm volatile("sfence");
		break;
	default:
		__asm volatile("lfence");
		break;
	}
}

#define	BUS_SPACE_MAP_CACHEABLE		0x0001
#define	BUS_SPACE_MAP_LINEAR		0x0002
#define	BUS_SPACE_MAP_PREFETCHABLE	0x0008

/*
 * Values for the x86 bus space tag, not to be used directly by MI code.
 */

/* space is i/o space */
extern const struct x86_bus_space_ops x86_bus_space_io_ops;
#define	X86_BUS_SPACE_IO	(&x86_bus_space_io_ops)

/* space is mem space */
extern const struct x86_bus_space_ops x86_bus_space_mem_ops;
#define X86_BUS_SPACE_MEM	(&x86_bus_space_mem_ops)

/*
 * bus_dma
 */

/*
 * Flags used in various bus DMA methods.
 */
#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		0x0010	/* placeholders for bus functions... */
#define	BUS_DMA_BUS2		0x0020
#define	BUS_DMA_32BIT		0x0040
#define	BUS_DMA_24BIT		0x0080	/* isadma map */
#define	BUS_DMA_STREAMING	0x0100	/* hint: sequential, unidirectional */
#define	BUS_DMA_READ		0x0200	/* mapping is device -> memory only */
#define	BUS_DMA_WRITE		0x0400	/* mapping is memory -> device only */
#define	BUS_DMA_NOCACHE		0x0800	/* map memory uncached */
#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_PREREAD	0x01
#define BUS_DMASYNC_POSTREAD	0x02
#define BUS_DMASYNC_PREWRITE	0x04
#define BUS_DMASYNC_POSTWRITE	0x08

typedef struct bus_dma_tag		*bus_dma_tag_t;
typedef struct bus_dmamap		*bus_dmamap_t;

/*
 *	bus_dma_segment_t
 *
 *	Describes a single contiguous DMA transaction.  Values
 *	are suitable for programming into DMA registers.
 */
struct bus_dma_segment {
	bus_addr_t	ds_addr;	/* DMA address */
	bus_size_t	ds_len;		/* length of transfer */
	/*
	 * Ugh. need this so can pass alignment down from bus_dmamem_alloc
	 * to scatter gather maps. only the first one is used so the rest is
	 * wasted space. bus_dma could do with fixing the api for this.
	 */
	 bus_size_t	_ds_boundary;	/* don't cross */
	 bus_size_t	_ds_align;	/* align to me */
};
typedef struct 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 bus_dma_tag {
	void	*_cookie;		/* cookie used in the guts */

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

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

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

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

/*
 *	bus_dmamap_t
 *
 *	Describes a DMA mapping.
 */
struct 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 */
};

int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
	    bus_size_t, int, bus_dmamap_t *);
void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
	    bus_size_t, struct proc *, int);
int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
	    struct mbuf *, int);
int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
	    struct uio *, int);
int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
	    bus_dma_segment_t *, int, bus_size_t, int);
void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
	    bus_size_t, int);

int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
	    bus_size_t alignment, bus_size_t boundary,
	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
	    int nsegs);
int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
	    int nsegs, size_t size, caddr_t *kvap, int flags);
void	_bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
	    size_t size);
paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
	    int nsegs, off_t off, int prot, int flags);

int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
	    bus_size_t alignment, bus_size_t boundary,
	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
	    bus_addr_t low, bus_addr_t high);

#endif /* _MACHINE_BUS_H_ */


code:
/*	$OpenBSD: cacheinfo.h,v 1.2 2012/03/16 01:53:00 haesbaert Exp $	*/
/*	$NetBSD: cacheinfo.h,v 1.1 2003/04/25 21:54:30 fvdl Exp $	*/

#ifndef _X86_CACHEINFO_H
#define _X86_CACHEINFO_H

struct x86_cache_info {
	uint8_t		cai_index;
	uint8_t		cai_desc;
	uint8_t		cai_associativity;
	u_int		cai_totalsize; /* #entries for TLB, bytes for cache */
	u_int		cai_linesize;	/* or page size for TLB */
	const char	*cai_string;
};

#define	CAI_ITLB	0		/* Instruction TLB (4K pages) */
#define	CAI_ITLB2	1		/* Instruction TLB (2/4M pages) */
#define	CAI_DTLB	2		/* Data TLB (4K pages) */
#define	CAI_DTLB2	3		/* Data TLB (2/4M pages) */
#define	CAI_ICACHE	4		/* Instruction cache */
#define	CAI_DCACHE	5		/* Data cache */
#define	CAI_L2CACHE	6		/* Level 2 cache */
#define	CAI_L3CACHE	7		/* Level 3 cache */

#define	CAI_COUNT	8

struct cpu_info;

const struct x86_cache_info *cache_info_lookup(const struct x86_cache_info *,
					       u_int8_t);
void amd_cpu_cacheinfo(struct cpu_info *);
void x86_print_cacheinfo(struct cpu_info *);

/*
 * AMD Cache Info:
 *
 *	Athlon, Duron:
 *
 *		Function 8000.0005 L1 TLB/Cache Information
 *		EAX -- L1 TLB 2/4MB pages
 *		EBX -- L1 TLB 4K pages
 *		ECX -- L1 D-cache
 *		EDX -- L1 I-cache
 *
 *		Function 8000.0006 L2 TLB/Cache Information
 *		EAX -- L2 TLB 2/4MB pages
 *		EBX -- L2 TLB 4K pages
 *		ECX -- L2 Unified cache
 *		EDX -- reserved
 *
 *	K5, K6:
 *
 *		Function 8000.0005 L1 TLB/Cache Information
 *		EAX -- reserved
 *		EBX -- TLB 4K pages
 *		ECX -- L1 D-cache
 *		EDX -- L1 I-cache
 *
 *	K6-III:
 *
 *		Function 8000.0006 L2 Cache Information
 *		EAX -- reserved
 *		EBX -- reserved
 *		ECX -- L2 Unified cache
 *		EDX -- reserved
 */

/* L1 TLB 2/4MB pages */
#define	AMD_L1_EAX_DTLB_ASSOC(x)	(((x) >> 24) & 0xff)
#define	AMD_L1_EAX_DTLB_ENTRIES(x)	(((x) >> 16) & 0xff)
#define	AMD_L1_EAX_ITLB_ASSOC(x)	(((x) >> 8)  & 0xff)
#define	AMD_L1_EAX_ITLB_ENTRIES(x)	( (x)        & 0xff)

/* L1 TLB 4K pages */
#define	AMD_L1_EBX_DTLB_ASSOC(x)	(((x) >> 24) & 0xff)
#define	AMD_L1_EBX_DTLB_ENTRIES(x)	(((x) >> 16) & 0xff)
#define	AMD_L1_EBX_ITLB_ASSOC(x)	(((x) >> 8)  & 0xff)
#define	AMD_L1_EBX_ITLB_ENTRIES(x)	( (x)        & 0xff)

/* L1 Data Cache */
#define	AMD_L1_ECX_DC_SIZE(x)		((((x) >> 24) & 0xff) * 1024)
#define	AMD_L1_ECX_DC_ASSOC(x)		 (((x) >> 16) & 0xff)
#define	AMD_L1_ECX_DC_LPT(x)		 (((x) >> 8)  & 0xff)
#define	AMD_L1_ECX_DC_LS(x)		 ( (x)        & 0xff)

/* L1 Instruction Cache */
#define	AMD_L1_EDX_IC_SIZE(x)		((((x) >> 24) & 0xff) * 1024)
#define	AMD_L1_EDX_IC_ASSOC(x)		 (((x) >> 16) & 0xff)
#define	AMD_L1_EDX_IC_LPT(x)		 (((x) >> 8)  & 0xff)
#define	AMD_L1_EDX_IC_LS(x)		 ( (x)        & 0xff)

/* Note for L2 TLB -- if the upper 16 bits are 0, it is a unified TLB */

/* L2 TLB 2/4MB pages */
#define	AMD_L2_EAX_DTLB_ASSOC(x)	(((x) >> 28)  & 0xf)
#define	AMD_L2_EAX_DTLB_ENTRIES(x)	(((x) >> 16)  & 0xfff)
#define	AMD_L2_EAX_IUTLB_ASSOC(x)	(((x) >> 12)  & 0xf)
#define	AMD_L2_EAX_IUTLB_ENTRIES(x)	( (x)         & 0xfff)

/* L2 TLB 4K pages */
#define	AMD_L2_EBX_DTLB_ASSOC(x)	(((x) >> 28)  & 0xf)
#define	AMD_L2_EBX_DTLB_ENTRIES(x)	(((x) >> 16)  & 0xfff)
#define	AMD_L2_EBX_IUTLB_ASSOC(x)	(((x) >> 12)  & 0xf)
#define	AMD_L2_EBX_IUTLB_ENTRIES(x)	( (x)         & 0xfff)

/* L2 Cache */
#define	AMD_L2_ECX_C_SIZE(x)		((((x) >> 16) & 0xffff) * 1024)
#define	AMD_L2_ECX_C_ASSOC(x)		 (((x) >> 12) & 0xf)
#define	AMD_L2_ECX_C_LPT(x)		 (((x) >> 8)  & 0xf)
#define	AMD_L2_ECX_C_LS(x)		 ( (x)        & 0xff)

/* L3 Cache */
#define	AMD_L3_EDX_C_SIZE(x)		((((x) >> 18) & 0x3fff) * 512 * 1024)
#define	AMD_L3_EDX_C_ASSOC(x)		 (((x) >> 12) & 0xf)
#define	AMD_L3_EDX_C_LPT(x)		 (((x) >> 8)  & 0xf)
#define	AMD_L3_EDX_C_LS(x)		 ( (x)        & 0xff)

#endif /* _X86_CACHEINFO_H */

license: unknown


code:
/*	$OpenBSD: cdefs.h,v 1.3 2013/03/28 17:30:45 martynas Exp $	*/

/*
 * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95.
 * Public domain.
 */

#ifndef	_MACHINE_CDEFS_H_
#define	_MACHINE_CDEFS_H_

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

#endif /* !_MACHINE_CDEFS_H_ */


code:
/*      $OpenBSD: codepatch.h,v 1.2 2015/04/19 19:45:21 sf Exp $    */
/*
 * Copyright (c) 2014-2015 Stefan Fritsch <sf@sfritsch.de>
 *
 * 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 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_CODEPATCH_H_
#define _MACHINE_CODEPATCH_H_

#include <machine/param.h>

#ifndef _LOCORE

void *codepatch_maprw(vaddr_t *nva, vaddr_t dest);
void codepatch_unmaprw(vaddr_t nva);
void codepatch_fill_nop(void *caddr, uint16_t len);
void codepatch_nop(uint16_t tag);
void codepatch_replace(uint16_t tag, void *code, size_t len);
void codepatch_call(uint16_t tag, void *func);

#endif /* !_LOCORE */

/*
 * Mark the start of some code snippet to be patched.
 */
#define	CODEPATCH_START	998:
/*
 * Mark the end of some code to be patched, and assign the given tag.
 */
#define	CODEPATCH_END(tag)			 \
	999:					 \
	.section .codepatch, "a"		;\
	.int (998b - KERNBASE)			;\
	.short (999b - 998b)			;\
	.short tag				;\
	.previous

#define CPTAG_STAC		1
#define CPTAG_CLAC		2
#define CPTAG_EOI		3

#endif /* _MACHINE_CODEPATCH_H_ */


code:
/*	$OpenBSD: conf.h,v 1.6 2011/07/04 16:52:41 nicm Exp $	*/
/*	$NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $	*/

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

#include <sys/conf.h>

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

bdev_decl(fd);
cdev_decl(fd);

cdev_decl(spkr);

#define biosselect seltrue
cdev_decl(bios);

#define	cdev_acpi_init(c,n) {\
	dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
	(dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
	(dev_type_stop((*))) enodev, 0, selfalse, \
	(dev_type_mmap((*))) enodev, 0, 0, dev_init(c,n,kqfilter) }
cdev_decl(acpi);

#define pctrpoll seltrue
cdev_decl(pctr);


code:
/*	$OpenBSD: cpu.h,v 1.97 2015/07/02 01:33:59 dlg Exp $	*/
/*	$NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $	*/

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

#ifndef _MACHINE_CPU_H_
#define _MACHINE_CPU_H_

/*
 * Definitions unique to x86-64 cpu support.
 */
#ifdef _KERNEL
#include <machine/frame.h>
#include <machine/segments.h>
#include <machine/cacheinfo.h>
#include <machine/intrdefs.h>
#endif /* _KERNEL */

#include <sys/device.h>
#include <sys/sched.h>
#include <sys/sensors.h>

#ifdef _KERNEL

struct x86_64_tss;
struct cpu_info {
	struct device *ci_dev;
	struct cpu_info *ci_self;
	struct schedstate_percpu ci_schedstate; /* scheduler state */
	struct cpu_info *ci_next;

	struct proc *ci_curproc;
	u_int ci_cpuid;
	u_int ci_apicid;
	u_int32_t ci_randseed;

	u_int64_t ci_scratch;

	struct proc *ci_fpcurproc;
	struct proc *ci_fpsaveproc;
	int ci_fpsaving;

	struct pcb *ci_curpcb;
	struct pcb *ci_idle_pcb;

	struct intrsource *ci_isources[MAX_INTR_SOURCES];
	u_int64_t	ci_ipending;
	int		ci_ilevel;
	int		ci_idepth;
	int		ci_handled_intr_level;
	u_int64_t	ci_imask[NIPL];
	u_int64_t	ci_iunmask[NIPL];
#ifdef DIAGNOSTIC
	int		ci_mutex_level;
#endif

	volatile u_int	ci_flags;
	u_int32_t	ci_ipis;

	u_int32_t	ci_feature_flags;
	u_int32_t	ci_feature_eflags;
	u_int32_t	ci_feature_sefflags;
	u_int32_t	ci_feature_tpmflags;
	u_int32_t	ci_signature;
	u_int32_t	ci_family;
	u_int32_t	ci_model;
	u_int32_t	ci_cflushsz;
	u_int64_t	ci_tsc_freq;

	int		ci_inatomic;

#define ARCH_HAVE_CPU_TOPOLOGY
	u_int32_t	ci_smt_id;
	u_int32_t	ci_core_id;
	u_int32_t	ci_pkg_id;

	struct cpu_functions *ci_func;
	void (*cpu_setup)(struct cpu_info *);
	void (*ci_info)(struct cpu_info *);

	struct device	*ci_acpicpudev;
	volatile u_int	ci_mwait;
#define	MWAIT_IN_IDLE		0x1	/* don't need IPI to wake */
#define	MWAIT_KEEP_IDLING	0x2	/* cleared by other cpus to wake me */
#define	MWAIT_ONLY		0x4	/* set if all idle states use mwait */
#define	MWAIT_IDLING	(MWAIT_IN_IDLE | MWAIT_KEEP_IDLING)

	int		ci_want_resched;

	struct x86_cache_info ci_cinfo[CAI_COUNT];

	struct	x86_64_tss *ci_tss;
	char		*ci_gdt;

	volatile int	ci_ddb_paused;
#define CI_DDB_RUNNING		0
#define CI_DDB_SHOULDSTOP	1
#define CI_DDB_STOPPED		2
#define CI_DDB_ENTERDDB		3
#define CI_DDB_INDDB		4

#ifdef MULTIPROCESSOR
	struct srp_hazard	ci_srp_hazards[SRP_HAZARD_NUM];
#endif

	struct ksensordev	ci_sensordev;
	struct ksensor		ci_sensor;
#ifdef GPROF
	struct gmonparam	*ci_gmon;
#endif
};

#define CPUF_BSP	0x0001		/* CPU is the original BSP */
#define CPUF_AP		0x0002		/* CPU is an AP */
#define CPUF_SP		0x0004		/* CPU is only processor */
#define CPUF_PRIMARY	0x0008		/* CPU is active primary processor */

#define CPUF_IDENTIFY	0x0010		/* CPU may now identify */
#define CPUF_IDENTIFIED	0x0020		/* CPU has been identified */

#define CPUF_CONST_TSC	0x0040		/* CPU has constant TSC */
#define CPUF_USERSEGS_BIT	7	/* CPU has curproc's segments */
#define CPUF_USERSEGS	(1<<CPUF_USERSEGS_BIT)		/* and FS.base */

#define CPUF_PRESENT	0x1000		/* CPU is present */
#define CPUF_RUNNING	0x2000		/* CPU is running */
#define CPUF_PAUSE	0x4000		/* CPU is paused in DDB */
#define CPUF_GO		0x8000		/* CPU should start running */
#define CPUF_PARK	0x10000		/* CPU should self-park in real mode */

#define PROC_PC(p)	((p)->p_md.md_regs->tf_rip)
#define PROC_STACK(p)	((p)->p_md.md_regs->tf_rsp)

extern struct cpu_info cpu_info_primary;
extern struct cpu_info *cpu_info_list;

#define CPU_INFO_ITERATOR		int
#define CPU_INFO_FOREACH(cii, ci)	for (cii = 0, ci = cpu_info_list; \
					    ci != NULL; ci = ci->ci_next)

#define CPU_INFO_UNIT(ci)	((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0)

/*
 * Preempt the current process if in interrupt from user mode,
 * or after the current trap/syscall if in system mode.
 */
extern void need_resched(struct cpu_info *);
#define clear_resched(ci) (ci)->ci_want_resched = 0

#if defined(MULTIPROCESSOR)

#define MAXCPUS		64	/* bitmask */

#define CPU_STARTUP(_ci)	((_ci)->ci_func->start(_ci))
#define CPU_STOP(_ci)		((_ci)->ci_func->stop(_ci))
#define CPU_START_CLEANUP(_ci)	((_ci)->ci_func->cleanup(_ci))

#define curcpu()	({struct cpu_info *__ci;                  \
			asm volatile("movq %%gs:8,%0" : "=r" (__ci)); \
			__ci;})
#define cpu_number()	(curcpu()->ci_cpuid)

#define CPU_IS_PRIMARY(ci)	((ci)->ci_flags & CPUF_PRIMARY)

extern struct cpu_info *cpu_info[MAXCPUS];

void cpu_boot_secondary_processors(void);
void cpu_init_idle_pcbs(void);

void cpu_kick(struct cpu_info *);
void cpu_unidle(struct cpu_info *);

#define CPU_BUSY_CYCLE()	__asm volatile("pause": : : "memory")

#else /* !MULTIPROCESSOR */

#define MAXCPUS		1

#ifdef _KERNEL
extern struct cpu_info cpu_info_primary;

#define curcpu()		(&cpu_info_primary)

#define cpu_kick(ci)
#define cpu_unidle(ci)

#define CPU_BUSY_CYCLE()	do {} while (0)

#endif

/*
 * definitions of cpu-dependent requirements
 * referenced in generic code
 */
#define	cpu_number()		0
#define CPU_IS_PRIMARY(ci)	1

#endif	/* MULTIPROCESSOR */

#include <machine/psl.h>

#endif /* _KERNEL */

#ifdef MULTIPROCESSOR
#include <sys/mplock.h>
#endif

#define aston(p)	((p)->p_md.md_astpending = 1)

#define curpcb		curcpu()->ci_curpcb

/*
 * Arguments to hardclock, softclock and statclock
 * encapsulate the previous machine state in an opaque
 * clockframe; for now, use generic intrframe.
 */
#define clockframe intrframe

#define	CLKF_USERMODE(frame)	USERMODE((frame)->if_cs, (frame)->if_rflags)
#define CLKF_PC(frame)		((frame)->if_rip)
#define CLKF_INTR(frame)	(curcpu()->ci_idepth > 1)

/*
 * This is used during profiling to integrate system time.
 */
#define	PROC_PC(p)		((p)->p_md.md_regs->tf_rip)

/*
 * Give a profiling tick to the current process when the user profiling
 * buffer pages are invalid.  On the i386, request an ast to send us
 * through trap(), marking the proc as needing a profiling tick.
 */
#define	need_proftick(p)	aston(p)

void signotify(struct proc *);

/*
 * We need a machine-independent name for this.
 */
extern void (*delay_func)(int);
struct timeval;

#define DELAY(x)		(*delay_func)(x)
#define delay(x)		(*delay_func)(x)

#ifdef _KERNEL
/* locore.S */
extern int biosbasemem;
extern int biosextmem;
extern int cpu;
extern int cpu_feature;
extern int cpu_ecxfeature;
extern int cpu_perf_eax;
extern int cpu_perf_ebx;
extern int cpu_perf_edx;
extern int cpu_apmi_edx;
extern int ecpu_ecxfeature;
extern int cpu_id;
extern char cpu_vendor[];
extern int cpuid_level;
extern int cpuspeed;

/* cpu.c */
extern u_int cpu_mwait_size;
extern u_int cpu_mwait_states;

/* identcpu.c */
void	identifycpu(struct cpu_info *);
int	cpu_amd64speed(int *);

/* machdep.c */
void	dumpconf(void);
void	cpu_reset(void);
void	x86_64_proc0_tss_ldt_init(void);
void	x86_64_bufinit(void);
void	x86_64_init_pcb_tss_ldt(struct cpu_info *);
void	cpu_proc_fork(struct proc *, struct proc *);
int	amd64_pa_used(paddr_t);
extern void (*cpu_idle_enter_fcn)(void);
extern void (*cpu_idle_cycle_fcn)(void);
extern void (*cpu_idle_leave_fcn)(void);

struct region_descriptor;
void	lgdt(struct region_descriptor *);

struct pcb;
void	savectx(struct pcb *);
void	switch_exit(struct proc *, void (*)(struct proc *));
void	proc_trampoline(void);

/* clock.c */
extern void (*initclock_func)(void);
void	startclocks(void);
void	rtcstart(void);
void	rtcstop(void);
void	i8254_delay(int);
void	i8254_initclocks(void);
void	i8254_startclock(void);
void	i8254_inittimecounter(void);
void	i8254_inittimecounter_simple(void);

/* i8259.c */
void	i8259_default_setup(void);

void cpu_init_msrs(struct cpu_info *);

/* trap.c */
void	child_return(void *);

/* dkcsum.c */
void	dkcsumattach(void);

/* bus_machdep.c */
void x86_bus_space_init(void);
void x86_bus_space_mallocok(void);

/* powernow-k8.c */
void k8_powernow_init(struct cpu_info *);
void k8_powernow_setperf(int);

/* k1x-pstate.c */
void k1x_init(struct cpu_info *);
void k1x_setperf(int);

void est_init(struct cpu_info *);
void est_setperf(int);

#ifdef MULTIPROCESSOR
/* mp_setperf.c */
void mp_setperf_init(void);
#endif

#endif /* _KERNEL */

/*
 * CTL_MACHDEP definitions.
 */
#define	CPU_CONSDEV		1	/* dev_t: console terminal device */
#define	CPU_BIOS		2	/* BIOS variables */
#define	CPU_BLK2CHR		3	/* convert blk maj into chr one */
#define	CPU_CHR2BLK		4	/* convert chr maj into blk one */
#define CPU_ALLOWAPERTURE	5	/* allow mmap of /dev/xf86 */
#define CPU_CPUVENDOR		6	/* cpuid vendor string */
#define CPU_CPUID		7	/* cpuid */
#define CPU_CPUFEATURE		8	/* cpuid features */
#define CPU_APMWARN		9	/* APM battery warning percentage */
#define CPU_KBDRESET		10	/* keyboard reset under pcvt */
#define CPU_APMHALT		11	/* halt -p hack */
#define CPU_XCRYPT		12	/* supports VIA xcrypt in userland */
#define CPU_LIDSUSPEND		13	/* lid close causes a suspend */
#define CPU_MAXID		14	/* number of valid machdep ids */

#define	CTL_MACHDEP_NAMES { \
	{ 0, 0 }, \
	{ "console_device", CTLTYPE_STRUCT }, \
	{ "bios", CTLTYPE_INT }, \
	{ "blk2chr", CTLTYPE_STRUCT }, \
	{ "chr2blk", CTLTYPE_STRUCT }, \
	{ "allowaperture", CTLTYPE_INT }, \
	{ "cpuvendor", CTLTYPE_STRING }, \
	{ "cpuid", CTLTYPE_INT }, \
	{ "cpufeature", CTLTYPE_INT }, \
	{ "apmwarn", CTLTYPE_INT }, \
	{ "kbdreset", CTLTYPE_INT }, \
	{ "apmhalt", CTLTYPE_INT }, \
	{ "xcrypt", CTLTYPE_INT }, \
	{ "lidsuspend", CTLTYPE_INT }, \
}

/*
 * Default cr4 flags.
 * Doesn't really belong here, but doesn't really belong anywhere else
 * either. Just to avoid painful mismatches of cr4 flags since they are
 * set in three different places.
 */
#define CR4_DEFAULT (CR4_PAE|CR4_PGE|CR4_PSE|CR4_OSFXSR|CR4_OSXMMEXCPT)

#endif /* !_MACHINE_CPU_H_ */


code:
/*	$OpenBSD: cpufunc.h,v 1.12 2015/03/21 20:42:38 kettenis Exp $	*/
/*	$NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $	*/

/*-
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Charles M. Hannum.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _MACHINE_CPUFUNC_H_
#define	_MACHINE_CPUFUNC_H_

/*
 * Functions to provide access to i386-specific instructions.
 */

#include <sys/types.h>

#include <machine/specialreg.h>

static __inline void
x86_pause(void)
{
	/* nothing */
}

#ifdef _KERNEL

extern int cpu_feature;

static __inline void
invlpg(u_int64_t addr)
{
        __asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
}

static __inline void
lidt(void *p)
{
	__asm volatile("lidt (%0)" : : "r" (p) : "memory");
}

static __inline void
lldt(u_short sel)
{
	__asm volatile("lldt %0" : : "r" (sel));
}

static __inline void
ltr(u_short sel)
{
	__asm volatile("ltr %0" : : "r" (sel));
}

static __inline void
lcr8(u_int val)
{
	u_int64_t val64 = val;
	__asm volatile("movq %0,%%cr8" : : "r" (val64));
}

/*
 * Upper 32 bits are reserved anyway, so just keep this 32bits.
 */
static __inline void
lcr0(u_int val)
{
	u_int64_t val64 = val;
	__asm volatile("movq %0,%%cr0" : : "r" (val64));
}

static __inline u_int
rcr0(void)
{
	u_int64_t val64;
	u_int val;
	__asm volatile("movq %%cr0,%0" : "=r" (val64));
	val = val64;
	return val;
}

static __inline u_int64_t
rcr2(void)
{
	u_int64_t val;
	__asm volatile("movq %%cr2,%0" : "=r" (val));
	return val;
}

static __inline void
lcr3(u_int64_t val)
{
	__asm volatile("movq %0,%%cr3" : : "r" (val));
}

static __inline u_int64_t
rcr3(void)
{
	u_int64_t val;
	__asm volatile("movq %%cr3,%0" : "=r" (val));
	return val;
}

/*
 * Same as for cr0. Don't touch upper 32 bits.
 */
static __inline void
lcr4(u_int val)
{
	u_int64_t val64 = val;

	__asm volatile("movq %0,%%cr4" : : "r" (val64));
}

static __inline u_int
rcr4(void)
{
	u_int val;
	u_int64_t val64;
	__asm volatile("movq %%cr4,%0" : "=r" (val64));
	val = val64;
	return val;
}

static __inline void
tlbflush(void)
{
	u_int64_t val;
	__asm volatile("movq %%cr3,%0" : "=r" (val));
	__asm volatile("movq %0,%%cr3" : : "r" (val));
}

static __inline void
tlbflushg(void)
{
	/*
	 * Big hammer: flush all TLB entries, including ones from PTE's
	 * with the G bit set.  This should only be necessary if TLB
	 * shootdown falls far behind.
	 *
	 * Intel Architecture Software Developer's Manual, Volume 3,
	 *	System Programming, section 9.10, "Invalidating the
	 * Translation Lookaside Buffers (TLBS)":
	 * "The following operations invalidate all TLB entries, irrespective
	 * of the setting of the G flag:
	 * ...
	 * "(P6 family processors only): Writing to control register CR4 to
	 * modify the PSE, PGE, or PAE flag."
	 *
	 * (the alternatives not quoted above are not an option here.)
	 *
	 * If PGE is not in use, we reload CR3 for the benefit of
	 * pre-P6-family processors.
	 */

	if (cpu_feature & CPUID_PGE) {
		u_int cr4 = rcr4();
		lcr4(cr4 & ~CR4_PGE);
		lcr4(cr4);
	} else
		tlbflush();
}

#ifdef notyet
void	setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl);
#endif

/* XXXX ought to be in psl.h with spl() functions */

static __inline void
disable_intr(void)
{
	__asm volatile("cli");
}

static __inline void
enable_intr(void)
{
	__asm volatile("sti");
}

static __inline u_long
read_rflags(void)
{
	u_long	ef;

	__asm volatile("pushfq; popq %0" : "=r" (ef));
	return (ef);
}

static __inline void
write_rflags(u_long ef)
{
	__asm volatile("pushq %0; popfq" : : "r" (ef));
}

static __inline u_int64_t
rdmsr(u_int msr)
{
	uint32_t hi, lo;
	__asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr));
	return (((uint64_t)hi << 32) | (uint64_t) lo);
}

static __inline void
wrmsr(u_int msr, u_int64_t newval)
{
	__asm volatile("wrmsr" :
	    : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr));
}

/*
 * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
 *
 * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
 */

#define	OPTERON_MSR_PASSCODE	0x9c5a203a

static __inline u_int64_t
rdmsr_locked(u_int msr, u_int code)
{
	uint32_t hi, lo;
	__asm volatile("rdmsr"
	    : "=d" (hi), "=a" (lo)
	    : "c" (msr), "D" (code));
	return (((uint64_t)hi << 32) | (uint64_t) lo);
}

static __inline void
wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
{
	__asm volatile("wrmsr" :
	    : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr), "D" (code));
}

static __inline void
wbinvd(void)
{
	__asm volatile("wbinvd");
}

static __inline void
clflush(u_int64_t addr)
{
	__asm volatile("clflush %0" : "+m" (*(volatile char *)addr));
}

static __inline void
mfence(void)
{
	__asm volatile("mfence" : : : "memory");
}

static __inline u_int64_t
rdtsc(void)
{
	uint32_t hi, lo;

	__asm volatile("rdtsc" : "=d" (hi), "=a" (lo));
	return (((uint64_t)hi << 32) | (uint64_t) lo);
}

static __inline u_int64_t
rdpmc(u_int pmc)
{
	uint32_t hi, lo;

	__asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc));
	return (((uint64_t)hi << 32) | (uint64_t) lo);
}

static __inline void
monitor(const volatile void *addr, u_long extensions, u_int hints)
{

	__asm volatile("monitor"
	    : : "a" (addr), "c" (extensions), "d" (hints));
}

static __inline void
mwait(u_long extensions, u_int hints)
{

	__asm volatile("mwait" : : "a" (hints), "c" (extensions));
}

static __inline void
xsetbv(uint32_t reg, uint64_t mask)
{
	uint32_t lo, hi;

	lo = mask;
	hi = mask >> 32;
	__asm volatile("xsetbv" :: "c" (reg), "a" (lo), "d" (hi) : "memory");
}

/* Break into DDB/KGDB. */
static __inline void
breakpoint(void)
{
	__asm volatile("int $3");
}

#define read_psl()	read_rflags()
#define write_psl(x)	write_rflags(x)

void amd64_errata(struct cpu_info *);

#endif /* _KERNEL */

#endif /* !_MACHINE_CPUFUNC_H_ */


code:
/*	$OpenBSD: cpuvar.h,v 1.7 2015/07/18 19:21:03 sf Exp $	*/
/* 	$NetBSD: cpuvar.h,v 1.1 2003/03/01 18:29:28 fvdl Exp $ */

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by RedBack Networks Inc.
 *
 * Author: Bill Sommerfeld
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 1999 Stefan Grefen
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the NetBSD
 *      Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR AND 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.
 */

struct cpu_functions {
	int (*start)(struct cpu_info *);
	int (*stop)(struct cpu_info *);
	void (*cleanup)(struct cpu_info *);
};

extern struct cpu_functions mp_cpu_funcs;

#define CPU_ROLE_SP	0
#define CPU_ROLE_BP	1
#define CPU_ROLE_AP	2

struct cpu_attach_args {
	const char *caa_name;
	int cpu_number;
	int cpu_role;
	struct cpu_functions *cpu_func;
};

#define MP_PICMODE	0x00000001      /* System booted in picmode */

#ifdef _KERNEL

#ifdef MULTIPROCESSOR
extern void (*x86_ipi)(int,int,int);
void x86_ipi_init(int);
#endif

void identifycpu(struct cpu_info *);
void cpu_init(struct cpu_info *);
void cpu_init_first(void);

#endif


code:
/*	$OpenBSD: db_machdep.h,v 1.12 2014/03/16 20:31:45 guenther Exp $	*/
/*	$NetBSD: db_machdep.h,v 1.2 2003/04/29 17:06:04 scw Exp $	*/

/*
 * Mach Operating System
 * Copyright (c) 1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */

#ifndef	_MACHINE_DB_MACHDEP_H_
#define	_MACHINE_DB_MACHDEP_H_

/*
 * Machine-dependent defines for new kernel debugger.
 */

#include <sys/param.h>
#include <uvm/uvm_extern.h>
#include <machine/trap.h>
#include <sys/mutex.h>

typedef	vaddr_t		db_addr_t;	/* address - unsigned */
typedef	long		db_expr_t;	/* expression - signed */

typedef struct trapframe db_regs_t;

extern db_regs_t ddb_regs;	/* register state */
#define	DDB_REGS	(&ddb_regs)

#define	PC_REGS(regs)	((db_addr_t)(regs)->tf_rip)
#define	SET_PC_REGS(regs, value) (regs)->tf_rip = (int64_t)(value)

#define	BKPT_ADDR(addr)	(addr)		/* breakpoint address */
#define	BKPT_INST	0xcc		/* breakpoint instruction */
#define	BKPT_SIZE	(1)		/* size of breakpoint inst */
#define	BKPT_SET(inst)	(BKPT_INST)

#define	FIXUP_PC_AFTER_BREAK(regs)	((regs)->tf_rip -= BKPT_SIZE)

#define	db_clear_single_step(regs)	((regs)->tf_rflags &= ~PSL_T)
#define	db_set_single_step(regs)	((regs)->tf_rflags |=  PSL_T)

#define	IS_BREAKPOINT_TRAP(type, code)	((type) == T_BPTFLT)
#define IS_WATCHPOINT_TRAP(type, code)	((type) == T_TRCTRAP && (code) & 15)

#define	I_CALL		0xe8
#define	I_CALLI		0xff
#define	I_RET		0xc3
#define	I_IRET		0xcf

#define	inst_trap_return(ins)	(((ins)&0xff) == I_IRET)
#define	inst_return(ins)	(((ins)&0xff) == I_RET)
#define	inst_call(ins)		(((ins)&0xff) == I_CALL || \
				 (((ins)&0xff) == I_CALLI && \
				  ((ins)&0x3800) == 0x1000))

/*
 * Constants for KGDB.
 */
typedef	long		kgdb_reg_t;
#define	KGDB_NUMREGS	20
#define	KGDB_BUFLEN	512

#define KGDB_ENTER	breakpoint()

/* macro for checking if a thread has used floating-point */

int kdb_trap(int, int, db_regs_t *);

void db_machine_init(void);
int db_enter_ddb(void);
void db_startcpu(int);
void db_stopcpu(int);
void x86_ipi_db(struct cpu_info *);

extern struct mutex ddb_mp_mutex;

#define DDB_STATE_NOT_RUNNING	0
#define DDB_STATE_RUNNING	1
#define DDB_STATE_EXITING	2

/*
 * We define some of our own commands
 */
#define DB_MACHINE_COMMANDS

extern void db_machine_init(void);

extern void cpu_debug_dump(void);

#endif	/* _MACHINE_DB_MACHDEP_H_ */


code:
/*	$OpenBSD: disklabel.h,v 1.10 2007/06/20 18:15:45 deraadt Exp $	*/

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

#ifndef _MACHINE_DISKLABEL_H_
#define _MACHINE_DISKLABEL_H_

#define	LABELSECTOR	1		/* sector containing label */
#define	LABELOFFSET	0		/* offset of label in sector */
#define	MAXPARTITIONS	16		/* number of partitions */

#endif /* _MACHINE_DISKLABEL_H_ */


code:
/*	$OpenBSD: endian.h,v 1.6 2014/07/12 16:25:08 guenther Exp $	*/

/*-
 * Copyright (c) 1997 Niklas Hallqvist.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _MACHINE_ENDIAN_H_
#define _MACHINE_ENDIAN_H_

#ifdef __GNUC__

#define	__swap32md(x) __statement({					\
	__uint32_t __swap32md_x = (x);					\
									\
	__asm ("bswap %0" : "+r" (__swap32md_x));			\
	__swap32md_x;							\
})

#define	__swap64md(x) __statement({					\
	__uint64_t __swap64md_x = (x);					\
									\
	__asm ("bswapq %0" : "+r" (__swap64md_x));			\
	__swap64md_x;							\
})

#define	__swap16md(x) __statement({					\
	__uint16_t __swap16md_x = (x);					\
									\
	__asm ("rorw $8, %w0" : "+r" (__swap16md_x));			\
	__swap16md_x;							\
})

/* Tell sys/endian.h we have MD variants of the swap macros.  */
#define __HAVE_MD_SWAP

#endif	/* __GNUC__ */

#define _BYTE_ORDER _LITTLE_ENDIAN

#ifndef __FROM_SYS__ENDIAN
#include <sys/endian.h>
#endif

#endif /* _MACHINE_ENDIAN_H_ */


code:
/*	$OpenBSD: exec.h,v 1.4 2012/09/11 15:44:17 deraadt Exp $	*/
/*
 * Written by Artur Grabowski <art@openbsd.org> Public Domain
 */

#ifndef _MACHINE_EXEC_H_
#define _MACHINE_EXEC_H_

#define __LDPGSZ 4096

#define ARCH_ELFSIZE 64

#define ELF_TARG_CLASS		ELFCLASS64
#define ELF_TARG_DATA		ELFDATA2LSB
#define ELF_TARG_MACH		EM_AMD64

#define _NLIST_DO_ELF
#define _KERN_DO_ELF64

#endif


code:
/*	$OpenBSD: fenv.h,v 1.4 2011/05/25 21:46:49 martynas Exp $	*/
/*	$NetBSD: fenv.h,v 1.1 2010/07/31 21:47:54 joerg Exp $	*/

/*-
 * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef	_AMD64_FENV_H_
#define	_AMD64_FENV_H_

/*
 * Each symbol representing a floating point exception expands to an integer
 * constant expression with values, such that bitwise-inclusive ORs of _all
 * combinations_ of the constants result in distinct values.
 *
 * We use such values that allow direct bitwise operations on FPU/SSE registers.
 */
#define	FE_INVALID		0x01
#define	FE_DENORMAL		0x02
#define	FE_DIVBYZERO		0x04
#define	FE_OVERFLOW		0x08
#define	FE_UNDERFLOW		0x10
#define	FE_INEXACT		0x20

/*
 * The following symbol is simply the bitwise-inclusive OR of all floating-point
 * exception constants defined above.
 */
#define	FE_ALL_EXCEPT		(FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \
				 FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
#define	_SSE_MASK_SHIFT		7

/*
 * Each symbol representing the rounding direction, expands to an integer
 * constant expression whose value is distinct non-negative value.
 *
 * We use such values that allow direct bitwise operations on FPU/SSE registers.
 */
#define	FE_TONEAREST		0x000
#define	FE_DOWNWARD		0x400
#define	FE_UPWARD		0x800
#define	FE_TOWARDZERO		0xc00

/*
 * The following symbol is simply the bitwise-inclusive OR of all floating-point
 * rounding direction constants defined above.
 */
#define	_X87_ROUND_MASK		(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \
				 FE_TOWARDZERO)
#define	_SSE_ROUND_SHIFT	3

/*
 * fenv_t represents the entire floating-point environment.
 */
typedef	struct {
	struct {
		unsigned int __control;		/* Control word register */
		unsigned int __status;		/* Status word register */
		unsigned int __tag;		/* Tag word register */
		unsigned int __others[4];	/* EIP, Pointer Selector, etc */
	} __x87;
	unsigned int __mxcsr;			/* Control, status register */
} fenv_t;

/*
 * The following constant represents the default floating-point environment
 * (that is, the one installed at program startup) and has type pointer to
 * const-qualified fenv_t.
 *
 * It can be used as an argument to the functions within the <fenv.h> header
 * that manage the floating-point environment, namely fesetenv() and
 * feupdateenv().
 */
__BEGIN_DECLS
extern	fenv_t			__fe_dfl_env;
__END_DECLS
#define	FE_DFL_ENV		((const fenv_t *)&__fe_dfl_env)

/*
 * fexcept_t represents the floating-point status flags collectively, including
 * any status the implementation associates with the flags.
 *
 * A floating-point status flag is a system variable whose value is set (but
 * never cleared) when a floating-point exception is raised, which occurs as a
 * side effect of exceptional floating-point arithmetic to provide auxiliary
 * information.
 *
 * A floating-point control mode is a system variable whose value may be set by
 * the user to affect the subsequent behavior of floating-point arithmetic.
 */
typedef	unsigned int		fexcept_t;

#endif	/* !_AMD64_FENV_H_ */


code:
/*	$OpenBSD: fpu.h,v 1.11 2015/03/25 21:05:18 kettenis Exp $	*/
/*	$NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $	*/

#ifndef	_MACHINE_FPU_H_
#define	_MACHINE_FPU_H_

#include <sys/types.h>

/*
 * amd64 only uses the extended save/restore format used
 * by fxsave/fsrestore, to always deal with the SSE registers,
 * which are part of the ABI to pass floating point values.
 * Must be stored in memory on a 16-byte boundary.
 */

struct fxsave64 {
	u_int16_t  fx_fcw;
	u_int16_t  fx_fsw;
	u_int8_t   fx_ftw;
	u_int8_t   fx_unused1;
	u_int16_t  fx_fop;
	u_int64_t  fx_rip;
	u_int64_t  fx_rdp;
	u_int32_t  fx_mxcsr;
	u_int32_t  fx_mxcsr_mask;
	u_int64_t  fx_st[8][2];   /* 8 normal FP regs */
	u_int64_t  fx_xmm[16][2]; /* 16 SSE2 registers */
	u_int8_t   fx_unused3[96];
} __packed;

struct xstate_hdr {
	uint64_t	xstate_bv;
	uint64_t	xstate_xcomp_bv;
	uint8_t		xstate_rsrv0[0];
	uint8_t		xstate_rsrv[40];
} __packed;

struct savefpu {
	struct fxsave64 fp_fxsave;	/* see above */
	struct xstate_hdr fp_xstate;
	u_int64_t fp_ymm[16][2];
	u_int16_t fp_ex_sw;		/* saved status from last exception */
	u_int16_t fp_ex_tw;		/* saved tag from last exception */
};

/*
 * The i387 defaults to Intel extended precision mode and round to nearest,
 * with all exceptions masked.
 */
#define	__INITIAL_NPXCW__	0x037f
#define __INITIAL_MXCSR__ 	0x1f80
#define __INITIAL_MXCSR_MASK__	0xffbf

#ifdef _KERNEL
/*
 * XXX
 */
struct trapframe;
struct cpu_info;

extern size_t	fpu_save_len;
extern uint32_t	fpu_mxcsr_mask;
extern uint64_t	xsave_mask;

void fpuinit(struct cpu_info *);
void fpudrop(void);
void fpudiscard(struct proc *);
void fputrap(struct trapframe *);
void fpusave_proc(struct proc *, int);
void fpusave_cpu(struct cpu_info *, int);
void fpu_kernel_enter(void);
void fpu_kernel_exit(void);

#endif

#endif /* _MACHINE_FPU_H_ */


code:
/*	$OpenBSD: frame.h,v 1.5 2011/03/23 16:54:34 pirofti Exp $	*/
/*	$NetBSD: frame.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $	*/

/*-
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Charles M. Hannum.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

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

/*
 * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com
 */

#ifndef _MACHINE_FRAME_H_
#define _MACHINE_FRAME_H_

#include <sys/signal.h>
#include <machine/fpu.h>

/*
 * System stack frames.
 */

/*
 * Exception/Trap Stack Frame
 */
struct trapframe {
	int64_t	tf_rdi;
	int64_t	tf_rsi;
	int64_t	tf_rdx;
	int64_t	tf_rcx;
	int64_t tf_r8;
	int64_t tf_r9;
	int64_t tf_r10;
	int64_t tf_r11;
	int64_t tf_r12;
	int64_t tf_r13;
	int64_t tf_r14;
	int64_t tf_r15;
	int64_t	tf_rbp;
	int64_t	tf_rbx;
	int64_t	tf_rax;
	int64_t	tf_gs;
	int64_t	tf_fs;
	int64_t	tf_es;
	int64_t	tf_ds;
	int64_t	tf_trapno;
	/* below portion defined in hardware */
	int64_t	tf_err;
	int64_t	tf_rip;
	int64_t	tf_cs;
	int64_t	tf_rflags;
	/* These are pushed unconditionally on the x86-64 */
	int64_t	tf_rsp;
	int64_t	tf_ss;
};

/*
 * Interrupt stack frame
 */
struct intrframe {
	int64_t	if_ppl;
	int64_t	if_rdi;
	int64_t	if_rsi;
	int64_t	if_rdx;
	int64_t	if_rcx;
	int64_t if_r8;
	int64_t if_r9;
	int64_t if_r10;
	int64_t if_r11;
	int64_t if_r12;
	int64_t if_r13;
	int64_t if_r14;
	int64_t if_r15;
	int64_t	if_rbp;
	int64_t	if_rbx;
	int64_t	if_rax;
	int64_t	tf_gs;
	int64_t	tf_fs;
	int64_t	tf_es;
	int64_t	tf_ds;
	u_int64_t __if_trapno; /* for compat with trap frame - trapno */
	u_int64_t __if_err;	/* for compat with trap frame - err */
	/* below portion defined in hardware */
	int64_t	if_rip;
	int64_t	if_cs;
	int64_t	if_rflags;
	/* These are pushed unconditionally on the x86-64 */
	int64_t	if_rsp;
	int64_t	if_ss;
};

/*
 * Stack frame inside cpu_switch()
 */
struct switchframe {
	int64_t	sf_r15;
	int64_t	sf_r14;
	int64_t	sf_r13;
	int64_t	sf_r12;
	int64_t sf_rbp;
	int64_t	sf_rbx;
	int64_t	sf_rip;
};

#endif  /* _MACHINE_FRAME_H_ */


code:
/*	$OpenBSD: frameasm.h,v 1.9 2015/07/17 15:37:58 guenther Exp $	*/
/*	$NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $	*/

#ifndef _AMD64_MACHINE_FRAMEASM_H
#define _AMD64_MACHINE_FRAMEASM_H

/*
 * Macros to define pushing/popping frames for interrupts, traps
 * and system calls. Currently all the same; will diverge later.
 */

/*
 * These are used on interrupt or trap entry or exit.
 */
#define INTR_SAVE_GPRS \
	subq	$120,%rsp	; \
	movq	%r15,TF_R15(%rsp)	; \
	movq	%r14,TF_R14(%rsp)	; \
	movq	%r13,TF_R13(%rsp)	; \
	movq	%r12,TF_R12(%rsp)	; \
	movq	%r11,TF_R11(%rsp)	; \
	movq	%r10,TF_R10(%rsp)	; \
	movq	%r9,TF_R9(%rsp)		; \
	movq	%r8,TF_R8(%rsp)		; \
	movq	%rdi,TF_RDI(%rsp)	; \
	movq	%rsi,TF_RSI(%rsp)	; \
	movq	%rbp,TF_RBP(%rsp)	; \
	movq	%rbx,TF_RBX(%rsp)	; \
	movq	%rdx,TF_RDX(%rsp)	; \
	movq	%rcx,TF_RCX(%rsp)	; \
	movq	%rax,TF_RAX(%rsp)

#define	INTRENTRY \
	subq	$32,%rsp		; \
	testq	$SEL_RPL,56(%rsp)	; \
	je	98f			; \
	swapgs				; \
98: 	INTR_SAVE_GPRS

#define INTRFASTEXIT \
	jmp	intr_fast_exit

#define INTR_RECURSE_HWFRAME \
	movq	%rsp,%r10		; \
	movl	%ss,%r11d		; \
	pushq	%r11			; \
	pushq	%r10			; \
	pushfq				; \
	movl	%cs,%r11d		; \
	pushq	%r11			; \
	pushq	%r13			;

/*
 * Restore FS.base if it's not already in the CPU, and do the cli/swapgs.
 * Uses %rax, %rcx, and %rdx
 */
#define INTR_RESTORE_SELECTORS						\
	btsl	$CPUF_USERSEGS_BIT, CPUVAR(FLAGS)			; \
	jc	99f							; \
	movq	CPUVAR(CURPCB),%rdx	/* for below */			; \
	movq	PCB_FSBASE(%rdx),%rax					; \
	cmpq	$0,%rax							; \
	je	99f		/* setting %fs has zeroed FS.base */	; \
	movq	%rax,%rdx						; \
	shrq	$32,%rdx						; \
	movl	$MSR_FSBASE,%ecx					; \
	wrmsr								; \
99:	movw    $(GSEL(GUDATA_SEL, SEL_UPL)),%ax			; \
	cli								; \
	swapgs								; \
	movw	%ax,%gs

#define CHECK_ASTPENDING(reg)	movq	CPUVAR(CURPROC),reg		; \
				cmpq	$0, reg				; \
				je	99f				; \
				cmpl	$0, P_MD_ASTPENDING(reg)	; \
				99:

#define CLEAR_ASTPENDING(reg)	movl	$0, P_MD_ASTPENDING(reg)

#endif /* _AMD64_MACHINE_FRAMEASM_H */


code:
/*	$OpenBSD: gdt.h,v 1.5 2010/11/13 04:16:42 guenther Exp $	*/
/*	$NetBSD: gdt.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $	*/

/*-
 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by John T. Kohl and Charles M. Hannum.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

void gdt_init_cpu(struct cpu_info *);
void gdt_alloc_cpu(struct cpu_info *);


code:
/*	$OpenBSD: hibernate.h,v 1.6 2014/07/09 11:37:16 mlarkin Exp $	*/

/*
 * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
 *
 * 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 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/hibernate_var.h>

/* amd64 hibernate support structures and functions */

int	get_hibernate_info_md(union hibernate_info *);
void	hibernate_flush(void);
void	hibernate_enter_resume_mapping(vaddr_t, paddr_t, int);
int	hibernate_inflate_skip(union hibernate_info *, paddr_t);
int	hibernate_suspend(void);
void	hibernate_switch_stack_machdep(void);
void	hibernate_resume_machdep(void);
void	hibernate_activate_resume_pt_machdep(void);
void	hibernate_enable_intr_machdep(void);
void	hibernate_disable_intr_machdep(void);
#ifdef MULTIPROCESSOR
void	hibernate_quiesce_cpus(void);
void	hibernate_drop_to_real_mode(void);
#endif /* MULTIPROCESSOR */


code:
/*	$OpenBSD: hibernate_var.h,v 1.12 2014/12/08 07:12:37 mlarkin Exp $	*/

/*
 * Copyright (c) 2011 Mike Larkin <mlarkin@openbsd.org>
 *
 * 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 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.
 */

#define PIGLET_PAGE_MASK (L2_FRAME)

/*
 * PML4 table for resume
 */
#define HIBERNATE_PML4T		(PAGE_SIZE * 21)

/*
 * amd64 uses a PDPT to map the first 512GB phys mem plus one more
 * to map any ranges of phys mem past 512GB (if needed)
 */
#define HIBERNATE_PDPT_LOW	(PAGE_SIZE * 22)
#define HIBERNATE_PDPT_HI	(PAGE_SIZE * 23)

/*
 * amd64 uses one PD to map the first 1GB phys mem plus one more to map any
 * other 1GB ranges within the first 512GB phys, plus one more to map any
 * 1GB range in any subsequent 512GB range
 */
#define HIBERNATE_PD_LOW	(PAGE_SIZE * 24)
#define HIBERNATE_PD_LOW2	(PAGE_SIZE * 25)
#define HIBERNATE_PD_HI		(PAGE_SIZE * 26)

/*
 * amd64 uses one PT to map the first 2MB phys mem plus one more to map any
 * other 2MB range within the first 1GB, plus one more to map any 2MB range
 * in any subsequent 512GB range.
 */
#define HIBERNATE_PT_LOW	(PAGE_SIZE * 27)
#define HIBERNATE_PT_LOW2	(PAGE_SIZE * 28)
#define HIBERNATE_PT_HI		(PAGE_SIZE * 29)

/* 3 pages for stack */
#define HIBERNATE_STACK_PAGE	(PAGE_SIZE * 32)

#define HIBERNATE_INFLATE_PAGE	(PAGE_SIZE * 33)
/* HIBERNATE_HIBALLOC_PAGE must be the last stolen page (see machdep.c) */
#define HIBERNATE_HIBALLOC_PAGE	(PAGE_SIZE * 34)

/* Use 4MB hibernation chunks */
#define HIBERNATE_CHUNK_SIZE		0x400000

#define HIBERNATE_CHUNK_TABLE_SIZE	0x100000

#define HIBERNATE_STACK_OFFSET	0x0F00


code:
/*	$OpenBSD: i82093reg.h,v 1.5 2015/04/19 19:45:21 sf Exp $	*/
/* 	$NetBSD: i82093reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by RedBack Networks Inc.
 *
 * Author: Bill Sommerfeld
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Typically, the first apic lives here.
 */
#define IOAPIC_BASE_DEFAULT	0xfec00000

/*
 * Memory-space registers.
 */

/*
 * The externally visible registers are all 32 bits wide;
 * store the register number of interest in IOAPIC_REG, and store/fetch
 * the real value in IOAPIC_DATA.
 */
#define	IOAPIC_REG		0x0000
#define IOAPIC_DATA		0x0010

/*
 * Internal I/O APIC registers.
 */

#define IOAPIC_ID		0x00

#define 	IOAPIC_ID_SHIFT		24
#define		IOAPIC_ID_MASK		0x0f000000

/* Version, and maximum interrupt pin number. */

#define IOAPIC_VER		0x01

#define		IOAPIC_VER_SHIFT		0
#define		IOAPIC_VER_MASK			0x000000ff

#define		IOAPIC_MAX_SHIFT	       	16
#define		IOAPIC_MAX_MASK	       	0x00ff0000

/*
 * Arbitration ID.  Same format as IOAPIC_ID register.
 */
#define IOAPIC_ARB		0x02

/*
 * Redirection table registers.
 */

#define IOAPIC_REDHI(pin)	(0x11 + ((pin)<<1))
#define IOAPIC_REDLO(pin)	(0x10 + ((pin)<<1))

#define IOAPIC_REDHI_DEST_SHIFT		24	   /* destination. */
#define IOAPIC_REDHI_DEST_MASK		0xff000000

#define IOAPIC_REDLO_MASK		0x00010000 /* 0=enabled; 1=masked */

#define IOAPIC_REDLO_LEVEL		0x00008000 /* 0=edge, 1=level */
#define IOAPIC_REDLO_RIRR		0x00004000 /* remote IRR; read only */
#define IOAPIC_REDLO_ACTLO		0x00002000 /* 0=act. hi; 1=act. lo */
#define IOAPIC_REDLO_DELSTS		0x00001000 /* 0=idle; 1=send pending */
#define IOAPIC_REDLO_DSTMOD		0x00000800 /* 0=physical; 1=logical */

#define IOAPIC_REDLO_DEL_MASK		0x00000700 /* del. mode mask */
#define IOAPIC_REDLO_DEL_SHIFT		8

#define IOAPIC_REDLO_DEL_FIXED		0
#define IOAPIC_REDLO_DEL_LOPRI		1
#define IOAPIC_REDLO_DEL_SMI		2
#define IOAPIC_REDLO_DEL_NMI		4
#define IOAPIC_REDLO_DEL_INIT		5
#define IOAPIC_REDLO_DEL_EXTINT		7

#define IOAPIC_REDLO_VECTOR_MASK	0x000000ff /* delivery vector */

#define IMCR_ADDR		0x22
#define IMCR_DATA		0x23

#define IMCR_REGISTER		0x70
#define		IMCR_PIC	0x00
#define 	IMCR_APIC	0x01

#ifdef _KERNEL

#include <machine/codepatch.h>

#define ioapic_asm_ack(num) 					 \
	CODEPATCH_START						;\
	movl	$0,(_C_LABEL(local_apic)+LAPIC_EOI)(%rip)	;\
	CODEPATCH_END(CPTAG_EOI)

#ifdef MULTIPROCESSOR

#ifdef notyet
#define ioapic_asm_lock(num) \
	movl	$1,%esi						;\
77:								\
	xchgl	%esi,PIC_LOCK(%rdi)				;\
	testl	%esi,%esi					;\
	jne	77b

#define ioapic_asm_unlock(num) \
	movl	$0,PIC_LOCK(%rdi)
#else
#define ioapic_asm_lock(num)
#define ioapic_asm_unlock(num)
#endif

#else

#define ioapic_asm_lock(num)
#define ioapic_asm_unlock(num)

#endif	/* MULTIPROCESSOR */

#define ioapic_mask(num) \
	movq	IS_PIC(%r14),%rdi				;\
	ioapic_asm_lock(num)					;\
	movl	IS_PIN(%r14),%esi				;\
	leaq	0x10(%rsi,%rsi,1),%rsi				;\
	movq	IOAPIC_SC_REG(%rdi),%r15			;\
	movl	%esi, (%r15)					;\
	movq	IOAPIC_SC_DATA(%rdi),%r15			;\
	movl	(%r15),%esi					;\
	orl	$IOAPIC_REDLO_MASK,%esi				;\
	movl	%esi,(%r15)					;\
	ioapic_asm_unlock(num)

#define ioapic_unmask(num) \
	cmpq	$IREENT_MAGIC,(TF_ERR+8)(%rsp)			;\
	jne	79f						;\
	movq	IS_PIC(%r14),%rdi				;\
	ioapic_asm_lock(num)					;\
	movl	IS_PIN(%r14),%esi				;\
	leaq	0x10(%rsi,%rsi,1),%rsi				;\
	movq	IOAPIC_SC_REG(%rdi),%r15			;\
	movq	IOAPIC_SC_DATA(%rdi),%r13			;\
	movl	%esi, (%r15)					;\
	movl	(%r13),%r12d					;\
	andl	$~IOAPIC_REDLO_MASK,%r12d			;\
	movl	%esi,(%r15)					;\
	movl	%r12d,(%r13)					;\
	ioapic_asm_unlock(num)					;\
79:

#endif


code:
/*	$OpenBSD: i82093var.h,v 1.4 2011/05/21 15:58:27 kettenis Exp $	*/
/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by RedBack Networks Inc.
 *
 * Author: Bill Sommerfeld
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _MACHINE_I82093VAR_H_
#define _MACHINE_I82093VAR_H_

#include <machine/apicvar.h>

struct ioapic_pin
{
	struct ioapic_pin	*ip_next;	/* next pin on this vector */
	struct mp_intr_map 	*ip_map;
	int			ip_vector;	/* IDT vector */
	int			ip_type;
	struct cpu_info		*ip_cpu;	/* target CPU */
};

struct ioapic_softc {
	struct pic		sc_pic;
	struct ioapic_softc	*sc_next;
	int			sc_apicid;
	int			sc_apic_vers;
	int			sc_apic_vecbase; /* global int base if ACPI */
	int			sc_apic_sz;	/* apic size*/
	int			sc_flags;
	paddr_t			sc_pa;		/* PA of ioapic */
	volatile u_int32_t	*sc_reg;	/* KVA of ioapic addr */
	volatile u_int32_t	*sc_data;	/* KVA of ioapic data */
	struct ioapic_pin	*sc_pins;	/* sc_apic_sz entries */
};

/*
 * MP: intr_handle_t is bitfielded.
 * ih&0xff -> legacy irq number.
 * ih&0x10000000 -> if 0, old-style isa irq; if 1, routed via ioapic.
 * (ih&0xff0000)>>16 -> ioapic id.
 * (ih&0x00ff00)>>8 -> ioapic pin.
 */

#define APIC_INT_VIA_APIC	0x10000000
#define APIC_INT_VIA_MSG	0x20000000
#define APIC_INT_APIC_MASK	0x00ff0000
#define APIC_INT_APIC_SHIFT	16
#define APIC_INT_PIN_MASK	0x0000ff00
#define APIC_INT_PIN_SHIFT	8

#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT)
#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT)
#define APIC_IRQ_ISLEGACY(x) (!((x) & APIC_INT_VIA_APIC))
#define APIC_IRQ_LEGACY_IRQ(x) ((x) & 0xff)

void *apic_intr_establish(int, int, int, int (*)(void *), void *);
void apic_intr_disestablish(void *);

void ioapic_print_redir(struct ioapic_softc *, char *, int);
void ioapic_format_redir(char *, char *, int, u_int32_t, u_int32_t);
struct ioapic_softc *ioapic_find(int);
struct ioapic_softc *ioapic_find_bybase(int);

void ioapic_enable(void);
void lapic_vectorset(void); /* XXX */

extern int ioapic_bsp_id;
extern int nioapics;
extern struct ioapic_softc *ioapics;

#endif /* !_MACHINE_I82093VAR_H_ */


code:
/*	$OpenBSD: i82489reg.h,v 1.4 2015/07/21 04:48:33 uebayasi Exp $	*/
/*	$NetBSD: i82489reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $	*/

/*-
 * Copyright (c) 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Frank van der Linden.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Registers and constants for the 82489DX and Pentium (and up) integrated
 * "local" APIC.
 */

#define	LAPIC_ID		0x020		/* ID. RW */
#	define LAPIC_ID_MASK		0x0f000000
#	define LAPIC_ID_SHIFT		24

#define LAPIC_VERS		0x030		/* Version. R */
#	define LAPIC_VERSION_MASK	0x000000ff
#	define LAPIC_VERSION_LVT_MASK	0x00ff0000
#	define LAPIC_VERSION_LVT_SHIFT	16

#define LAPIC_TPRI		0x080		/* Task Prio. RW */
#	define LAPIC_TPRI_MASK		0x000000ff
#	define LAPIC_TPRI_INT_MASK	0x000000f0
#	define LAPIC_TPRI_SUB_MASK	0x0000000f

#define LAPIC_APRI		0x090		/* Arbitration prio R */
#	define LAPIC_APRI_MASK		0x000000ff

#define LAPIC_PPRI		0x0a0		/* Processor prio. R */
#define LAPIC_EOI		0x0b0		/* End Int. W */
#define LAPIC_RRR		0x0c0		/* Remote read R */
#define LAPIC_LDR		0x0d0		/* Logical dest. RW */
#define LAPIC_DFR		0x0e0		/* Dest. format RW */

#define LAPIC_SVR		0x0f0		/* Spurious intvec RW */
#	define LAPIC_SVR_VECTOR_MASK	0x000000ff
#	define LAPIC_SVR_VEC_FIX	0x0000000f
#	define LAPIC_SVR_VEC_PROG	0x000000f0
#	define LAPIC_SVR_ENABLE		0x00000100
#	define LAPIC_SVR_SWEN		0x00000100
#	define LAPIC_SVR_FOCUS		0x00000200
#	define LAPIC_SVR_FDIS		0x00000200

#define LAPIC_ISR	0x100			/* Int. status. R */
#define LAPIC_TMR	0x180
#define LAPIC_IRR	0x200
#define LAPIC_ESR	0x280			/* Err status. R */

#define LAPIC_ICRLO	0x300			/* Int. cmd. RW */
#	define LAPIC_DLMODE_MASK	0x00000700
#	define LAPIC_DLMODE_FIXED	0x00000000
#	define LAPIC_DLMODE_LOW		0x00000100
#	define LAPIC_DLMODE_SMI		0x00000200
#	define LAPIC_DLMODE_RR		0x00000300
#	define LAPIC_DLMODE_NMI		0x00000400
#	define LAPIC_DLMODE_INIT	0x00000500
#	define LAPIC_DLMODE_STARTUP	0x00000600

#	define LAPIC_DSTMODE_LOG	0x00000800

#	define LAPIC_DLSTAT_BUSY	0x00001000

#	define LAPIC_LVL_ASSERT		0x00004000
#	define LAPIC_LVL_DEASSERT	0x00000000

#	define LAPIC_LVL_TRIG		0x00008000

#	define LAPIC_RRSTAT_MASK	0x00030000
#	define LAPIC_RRSTAT_INPROG	0x00010000
#	define LAPIC_RRSTAT_VALID	0x00020000

#	define LAPIC_DEST_MASK		0x000c0000
#	define LAPIC_DEST_SELF		0x00040000
#	define LAPIC_DEST_ALLINCL	0x00080000
#	define LAPIC_DEST_ALLEXCL	0x000c0000

#	define LAPIC_RESV2_MASK		0xfff00000

#define LAPIC_ICRHI	0x310			/* Int. cmd. RW */
#	define LAPIC_ID_MASK		0x0f000000
#	define LAPIC_ID_SHIFT		24

#define LAPIC_LVTT	0x320			/* Loc.vec.(timer) RW */
#	define LAPIC_LVTT_VEC_MASK	0x000000ff
#	define LAPIC_LVTT_DS		0x00001000
#	define LAPIC_LVTT_M		0x00010000
#	define LAPIC_LVTT_TM		0x00020000
#	 define LAPIC_LVTT_TM_ONESHOT	0x00000000
#	 define LAPIC_LVTT_TM_PERIODIC	0x00020000
#	 define LAPIC_LVTT_TM_TSCDL	0x00040000

#define LAPIC_PCINT	0x340
#define LAPIC_LVINT0	0x350			/* Loc.vec (LINT0) RW */
#	define LAPIC_LVT_PERIODIC	0x00020000
#	define LAPIC_LVT_MASKED		0x00010000
#	define LAPIC_LVT_LEVTRIG	0x00008000
#	define LAPIC_LVT_REMOTE_IRR	0x00004000
#	define LAPIC_INP_POL		0x00002000
#	define LAPIC_PEND_SEND		0x00001000

#define LAPIC_LVINT1	0x360			/* Loc.vec (LINT1) RW */
#define LAPIC_LVERR	0x370			/* Loc.vec (ERROR) RW */
#define LAPIC_ICR_TIMER	0x380			/* Initial count RW */
#define LAPIC_CCR_TIMER	0x390			/* Current count RO */

#define LAPIC_DCR_TIMER	0x3e0			/* Divisor config register */
#	define LAPIC_DCRT_DIV1		0x0b
#	define LAPIC_DCRT_DIV2		0x00
#	define LAPIC_DCRT_DIV4		0x01
#	define LAPIC_DCRT_DIV8		0x02
#	define LAPIC_DCRT_DIV16		0x03
#	define LAPIC_DCRT_DIV32		0x08
#	define LAPIC_DCRT_DIV64		0x09
#	define LAPIC_DCRT_DIV128	0x0a

#define LAPIC_BASE		0xfee00000

#define LAPIC_IRQ_MASK(i)	(1 << ((i) + 1))

#define	MSR_X2APIC_BASE		0x800
#define	MSR_X2APIC_EOI		(MSR_X2APIC_BASE+0x0b)	/* End Int. W */
#define	MSR_X2APIC_ID		(MSR_X2APIC_BASE+0x02)	/* ID. RW */
#define	X2APIC_ID_MASK		0xff