diff options
Diffstat (limited to 'freebsd/sys/i386')
-rw-r--r-- | freebsd/sys/i386/i386/in_cksum.c | 493 | ||||
-rw-r--r-- | freebsd/sys/i386/i386/legacy.c | 347 | ||||
-rw-r--r-- | freebsd/sys/i386/include/machine/cpufunc.h | 761 | ||||
-rw-r--r-- | freebsd/sys/i386/include/machine/in_cksum.h | 171 | ||||
-rw-r--r-- | freebsd/sys/i386/include/machine/intr_machdep.h | 161 | ||||
-rw-r--r-- | freebsd/sys/i386/include/machine/md_var.h | 106 | ||||
-rw-r--r-- | freebsd/sys/i386/include/machine/specialreg.h | 596 |
7 files changed, 2635 insertions, 0 deletions
diff --git a/freebsd/sys/i386/i386/in_cksum.c b/freebsd/sys/i386/i386/in_cksum.c new file mode 100644 index 00000000..0f663989 --- /dev/null +++ b/freebsd/sys/i386/i386/in_cksum.c @@ -0,0 +1,493 @@ +#include <freebsd/machine/rtems-bsd-config.h> + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from tahoe: in_cksum.c 1.2 86/01/05 + * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 + */ + +#include <freebsd/sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <freebsd/sys/param.h> +#include <freebsd/sys/systm.h> +#include <freebsd/sys/mbuf.h> + +#include <freebsd/netinet/in.h> +#include <freebsd/netinet/in_systm.h> +#include <freebsd/netinet/ip.h> + +#include <freebsd/machine/in_cksum.h> + +/* + * Checksum routine for Internet Protocol family headers. + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + * + * This implementation is 386 version. + */ + +#undef ADDCARRY +#define ADDCARRY(x) if ((x) > 0xffff) (x) -= 0xffff +/* + * icc needs to be special cased here, as the asm code below results + * in broken code if compiled with icc. + */ +#if !defined(__GNUCLIKE_ASM) || defined(__INTEL_COMPILER) +/* non gcc parts stolen from sys/alpha/alpha/in_cksum.c */ +#define REDUCE32 \ + { \ + q_util.q = sum; \ + sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + } +#define REDUCE16 \ + { \ + q_util.q = sum; \ + l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } +#endif +#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);} + +#if !defined(__GNUCLIKE_ASM) || defined(__INTEL_COMPILER) +static const u_int32_t in_masks[] = { + /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ + 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */ + 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */ + 0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */ + 0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */ +}; + +union l_util { + u_int16_t s[2]; + u_int32_t l; +}; +union q_util { + u_int16_t s[4]; + u_int32_t l[2]; + u_int64_t q; +}; + +static u_int64_t +in_cksumdata(const u_int32_t *lw, int len) +{ + u_int64_t sum = 0; + u_int64_t prefilled; + int offset; + union q_util q_util; + + if ((3 & (long) lw) == 0 && len == 20) { + sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; + REDUCE32; + return sum; + } + + if ((offset = 3 & (long) lw) != 0) { + const u_int32_t *masks = in_masks + (offset << 2); + lw = (u_int32_t *) (((long) lw) - offset); + sum = *lw++ & masks[len >= 3 ? 3 : len]; + len -= 4 - offset; + if (len <= 0) { + REDUCE32; + return sum; + } + } +#if 0 + /* + * Force to cache line boundary. + */ + offset = 32 - (0x1f & (long) lw); + if (offset < 32 && len > offset) { + len -= offset; + if (4 & offset) { + sum += (u_int64_t) lw[0]; + lw += 1; + } + if (8 & offset) { + sum += (u_int64_t) lw[0] + lw[1]; + lw += 2; + } + if (16 & offset) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + } +#endif + /* + * access prefilling to start load of next cache line. + * then add current cache line + * save result of prefilling for loop iteration. + */ + prefilled = lw[0]; + while ((len -= 32) >= 4) { + u_int64_t prefilling = lw[8]; + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + prefilled = prefilling; + } + if (len >= 0) { + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + } else { + len += 32; + } + while ((len -= 16) >= 0) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + len += 16; + while ((len -= 4) >= 0) { + sum += (u_int64_t) *lw++; + } + len += 4; + if (len > 0) + sum += (u_int64_t) (in_masks[len] & *lw); + REDUCE32; + return sum; +} + +u_short +in_addword(u_short a, u_short b) +{ + u_int64_t sum = a + b; + + ADDCARRY(sum); + return (sum); +} + +u_short +in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c) +{ + u_int64_t sum; + union q_util q_util; + union l_util l_util; + + sum = (u_int64_t) a + b + c; + REDUCE16; + return (sum); +} + +u_short +in_cksum_skip(struct mbuf *m, int len, int skip) +{ + u_int64_t sum = 0; + int mlen = 0; + int clen = 0; + caddr_t addr; + union q_util q_util; + union l_util l_util; + + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; + addr = mtod(m, caddr_t) + skip; + goto skip_start; + } else { + skip -= m->m_len; + } + } + + for (; m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + mlen = m->m_len; + addr = mtod(m, caddr_t); +skip_start: + if (len < mlen) + mlen = len; + if ((clen ^ (long) addr) & 1) + sum += in_cksumdata((const u_int32_t *)addr, mlen) << 8; + else + sum += in_cksumdata((const u_int32_t *)addr, mlen); + + clen += mlen; + len -= mlen; + } + REDUCE16; + return (~sum & 0xffff); +} + +u_int in_cksum_hdr(const struct ip *ip) +{ + u_int64_t sum = in_cksumdata((const u_int32_t *)ip, sizeof(struct ip)); + union q_util q_util; + union l_util l_util; + + REDUCE16; + return (~sum & 0xffff); +} +#else + +/* + * These asm statements require __volatile because they pass information + * via the condition codes. GCC does not currently provide a way to specify + * the condition codes as an input or output operand. + * + * The LOAD macro below is effectively a prefetch into cache. GCC will + * load the value into a register but will not use it. Since modern CPUs + * reorder operations, this will generally take place in parallel with + * other calculations. + */ +u_short +in_cksum_skip(m, len, skip) + struct mbuf *m; + int len; + int skip; +{ + register u_short *w; + register unsigned sum = 0; + register int mlen = 0; + int byte_swapped = 0; + union { char c[2]; u_short s; } su; + + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; + w = (u_short *)(mtod(m, u_char *) + skip); + goto skip_start; + } else { + skip -= m->m_len; + } + } + + for (;m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + w = mtod(m, u_short *); + if (mlen == -1) { + /* + * The first byte of this mbuf is the continuation + * of a word spanning between this mbuf and the + * last mbuf. + */ + + /* su.c[0] is already saved when scanning previous + * mbuf. sum was REDUCEd when we found mlen == -1 + */ + su.c[1] = *(u_char *)w; + sum += su.s; + w = (u_short *)((char *)w + 1); + mlen = m->m_len - 1; + len--; + } else + mlen = m->m_len; +skip_start: + if (len < mlen) + mlen = len; + len -= mlen; + /* + * Force to long boundary so we do longword aligned + * memory operations + */ + if (3 & (int) w) { + REDUCE; + if ((1 & (int) w) && (mlen > 0)) { + sum <<= 8; + su.c[0] = *(char *)w; + w = (u_short *)((char *)w + 1); + mlen--; + byte_swapped = 1; + } + if ((2 & (int) w) && (mlen >= 2)) { + sum += *w++; + mlen -= 2; + } + } + /* + * Advance to a 486 cache line boundary. + */ + if (4 & (int) w && mlen >= 4) { + __asm __volatile ( + "addl %1, %0\n" + "adcl $0, %0" + : "+r" (sum) + : "g" (((const u_int32_t *)w)[0]) + ); + w += 2; + mlen -= 4; + } + if (8 & (int) w && mlen >= 8) { + __asm __volatile ( + "addl %1, %0\n" + "adcl %2, %0\n" + "adcl $0, %0" + : "+r" (sum) + : "g" (((const u_int32_t *)w)[0]), + "g" (((const u_int32_t *)w)[1]) + ); + w += 4; + mlen -= 8; + } + /* + * Do as much of the checksum as possible 32 bits at at time. + * In fact, this loop is unrolled to make overhead from + * branches &c small. + */ + mlen -= 1; + while ((mlen -= 32) >= 0) { + /* + * Add with carry 16 words and fold in the last + * carry by adding a 0 with carry. + * + * The early ADD(16) and the LOAD(32) are to load + * the next 2 cache lines in advance on 486's. The + * 486 has a penalty of 2 clock cycles for loading + * a cache line, plus whatever time the external + * memory takes to load the first word(s) addressed. + * These penalties are unavoidable. Subsequent + * accesses to a cache line being loaded (and to + * other external memory?) are delayed until the + * whole load finishes. These penalties are mostly + * avoided by not accessing external memory for + * 8 cycles after the ADD(16) and 12 cycles after + * the LOAD(32). The loop terminates when mlen + * is initially 33 (not 32) to guaranteed that + * the LOAD(32) is within bounds. + */ + __asm __volatile ( + "addl %1, %0\n" + "adcl %2, %0\n" + "adcl %3, %0\n" + "adcl %4, %0\n" + "adcl %5, %0\n" + "mov %6, %%eax\n" + "adcl %7, %0\n" + "adcl %8, %0\n" + "adcl %9, %0\n" + "adcl $0, %0" + : "+r" (sum) + : "g" (((const u_int32_t *)w)[4]), + "g" (((const u_int32_t *)w)[0]), + "g" (((const u_int32_t *)w)[1]), + "g" (((const u_int32_t *)w)[2]), + "g" (((const u_int32_t *)w)[3]), + "g" (((const u_int32_t *)w)[8]), + "g" (((const u_int32_t *)w)[5]), + "g" (((const u_int32_t *)w)[6]), + "g" (((const u_int32_t *)w)[7]) + : "eax" + ); + w += 16; + } + mlen += 32 + 1; + if (mlen >= 32) { + __asm __volatile ( + "addl %1, %0\n" + "adcl %2, %0\n" + "adcl %3, %0\n" + "adcl %4, %0\n" + "adcl %5, %0\n" + "adcl %6, %0\n" + "adcl %7, %0\n" + "adcl %8, %0\n" + "adcl $0, %0" + : "+r" (sum) + : "g" (((const u_int32_t *)w)[4]), + "g" (((const u_int32_t *)w)[0]), + "g" (((const u_int32_t *)w)[1]), + "g" (((const u_int32_t *)w)[2]), + "g" (((const u_int32_t *)w)[3]), + "g" (((const u_int32_t *)w)[5]), + "g" (((const u_int32_t *)w)[6]), + "g" (((const u_int32_t *)w)[7]) + ); + w += 16; + mlen -= 32; + } + if (mlen >= 16) { + __asm __volatile ( + "addl %1, %0\n" + "adcl %2, %0\n" + "adcl %3, %0\n" + "adcl %4, %0\n" + "adcl $0, %0" + : "+r" (sum) + : "g" (((const u_int32_t *)w)[0]), + "g" (((const u_int32_t *)w)[1]), + "g" (((const u_int32_t *)w)[2]), + "g" (((const u_int32_t *)w)[3]) + ); + w += 8; + mlen -= 16; + } + if (mlen >= 8) { + __asm __volatile ( + "addl %1, %0\n" + "adcl %2, %0\n" + "adcl $0, %0" + : "+r" (sum) + : "g" (((const u_int32_t *)w)[0]), + "g" (((const u_int32_t *)w)[1]) + ); + w += 4; + mlen -= 8; + } + if (mlen == 0 && byte_swapped == 0) + continue; /* worth 1% maybe ?? */ + REDUCE; + while ((mlen -= 2) >= 0) { + sum += *w++; + } + if (byte_swapped) { + sum <<= 8; + byte_swapped = 0; + if (mlen == -1) { + su.c[1] = *(char *)w; + sum += su.s; + mlen = 0; + } else + mlen = -1; + } else if (mlen == -1) + /* + * This mbuf has odd number of bytes. + * There could be a word split betwen + * this mbuf and the next mbuf. + * Save the last byte (to prepend to next mbuf). + */ + su.c[0] = *(char *)w; + } + + if (len) + printf("%s: out of data by %d\n", __func__, len); + if (mlen == -1) { + /* The last mbuf has odd # of bytes. Follow the + standard (the odd byte is shifted left by 8 bits) */ + su.c[1] = 0; + sum += su.s; + } + REDUCE; + return (~sum & 0xffff); +} +#endif diff --git a/freebsd/sys/i386/i386/legacy.c b/freebsd/sys/i386/i386/legacy.c new file mode 100644 index 00000000..24021809 --- /dev/null +++ b/freebsd/sys/i386/i386/legacy.c @@ -0,0 +1,347 @@ +#include <freebsd/machine/rtems-bsd-config.h> + +/*- + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <freebsd/sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * This code implements a system driver for legacy systems that do not + * support ACPI or when ACPI support is not present in the kernel. + */ + +#include <freebsd/sys/param.h> +#include <freebsd/sys/systm.h> +#include <freebsd/sys/bus.h> +#include <freebsd/sys/cpu.h> +#include <freebsd/sys/kernel.h> +#include <freebsd/sys/malloc.h> +#include <freebsd/sys/module.h> +#include <freebsd/machine/bus.h> +#include <freebsd/sys/pcpu.h> +#include <freebsd/sys/rman.h> +#include <freebsd/sys/smp.h> + +#ifndef __rtems__ +#include <freebsd/local/opt_mca.h> +#endif /* __rtems__ */ +#ifdef DEV_MCA +#include <freebsd/i386/bios/mca_machdep.h> +#endif + +#include <freebsd/machine/legacyvar.h> +#include <freebsd/machine/resource.h> + +static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device"); +struct legacy_device { + int lg_pcibus; +}; + +#define DEVTOAT(dev) ((struct legacy_device *)device_get_ivars(dev)) + +static int legacy_probe(device_t); +static int legacy_attach(device_t); +static int legacy_print_child(device_t, device_t); +static device_t legacy_add_child(device_t bus, u_int order, const char *name, + int unit); +static int legacy_read_ivar(device_t, device_t, int, uintptr_t *); +static int legacy_write_ivar(device_t, device_t, int, uintptr_t); + +static device_method_t legacy_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, legacy_probe), + DEVMETHOD(device_attach, legacy_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, legacy_print_child), + DEVMETHOD(bus_add_child, legacy_add_child), + DEVMETHOD(bus_read_ivar, legacy_read_ivar), + DEVMETHOD(bus_write_ivar, legacy_write_ivar), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t legacy_driver = { + "legacy", + legacy_methods, + 1, /* no softc */ +}; +static devclass_t legacy_devclass; + +DRIVER_MODULE(legacy, nexus, legacy_driver, legacy_devclass, 0, 0); + +static int +legacy_probe(device_t dev) +{ + + device_set_desc(dev, "legacy system"); + device_quiet(dev); + return (0); +} + +static int +legacy_attach(device_t dev) +{ + device_t child; + + /* + * Let our child drivers identify any child devices that they + * can find. Once that is done attach any devices that we + * found. + */ + bus_generic_probe(dev); + bus_generic_attach(dev); + +#ifndef PC98 + /* + * If we didn't see EISA or ISA on a pci bridge, create some + * connection points now so they show up "on motherboard". + */ + if (!devclass_get_device(devclass_find("eisa"), 0)) { + child = BUS_ADD_CHILD(dev, 0, "eisa", 0); + if (child == NULL) + panic("legacy_attach eisa"); + device_probe_and_attach(child); + } +#endif +#ifdef DEV_MCA + if (MCA_system && !devclass_get_device(devclass_find("mca"), 0)) { + child = BUS_ADD_CHILD(dev, 0, "mca", 0); + if (child == 0) + panic("legacy_probe mca"); + device_probe_and_attach(child); + } +#endif + if (!devclass_get_device(devclass_find("isa"), 0)) { + child = BUS_ADD_CHILD(dev, 0, "isa", 0); + if (child == NULL) + panic("legacy_attach isa"); + device_probe_and_attach(child); + } + + return 0; +} + +static int +legacy_print_child(device_t bus, device_t child) +{ + struct legacy_device *atdev = DEVTOAT(child); + int retval = 0; + + retval += bus_print_child_header(bus, child); + if (atdev->lg_pcibus != -1) + retval += printf(" pcibus %d", atdev->lg_pcibus); + retval += printf(" on motherboard\n"); /* XXX "motherboard", ick */ + + return (retval); +} + +static device_t +legacy_add_child(device_t bus, u_int order, const char *name, int unit) +{ + device_t child; + struct legacy_device *atdev; + + atdev = malloc(sizeof(struct legacy_device), M_LEGACYDEV, + M_NOWAIT | M_ZERO); + if (atdev == NULL) + return(NULL); + atdev->lg_pcibus = -1; + + child = device_add_child_ordered(bus, order, name, unit); + if (child == NULL) + free(atdev, M_LEGACYDEV); + else + /* should we free this in legacy_child_detached? */ + device_set_ivars(child, atdev); + + return (child); +} + +static int +legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct legacy_device *atdev = DEVTOAT(child); + + switch (which) { + case LEGACY_IVAR_PCIDOMAIN: + *result = 0; + break; + case LEGACY_IVAR_PCIBUS: + *result = atdev->lg_pcibus; + break; + default: + return ENOENT; + } + return 0; +} + + +static int +legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct legacy_device *atdev = DEVTOAT(child); + + switch (which) { + case LEGACY_IVAR_PCIDOMAIN: + return EINVAL; + case LEGACY_IVAR_PCIBUS: + atdev->lg_pcibus = value; + break; + default: + return ENOENT; + } + return 0; +} + +/* + * Legacy CPU attachment when ACPI is not available. Drivers like + * cpufreq(4) hang off this. + */ +static void cpu_identify(driver_t *driver, device_t parent); +static int cpu_read_ivar(device_t dev, device_t child, int index, + uintptr_t *result); +static device_t cpu_add_child(device_t bus, u_int order, const char *name, + int unit); +static struct resource_list *cpu_get_rlist(device_t dev, device_t child); + +struct cpu_device { + struct resource_list cd_rl; + struct pcpu *cd_pcpu; +}; + +static device_method_t cpu_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, cpu_identify), + DEVMETHOD(device_probe, bus_generic_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_add_child, cpu_add_child), + DEVMETHOD(bus_read_ivar, cpu_read_ivar), + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_get_resource_list, cpu_get_rlist), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t cpu_driver = { + "cpu", + cpu_methods, + 1, /* no softc */ +}; +static devclass_t cpu_devclass; +DRIVER_MODULE(cpu, legacy, cpu_driver, cpu_devclass, 0, 0); + +static void +cpu_identify(driver_t *driver, device_t parent) +{ + device_t child; + int i; + + /* + * Attach a cpuX device for each CPU. We use an order of 150 + * so that these devices are attached after the Host-PCI + * bridges (which are added at order 100). + */ + for (i = 0; i <= mp_maxid; i++) + if (!CPU_ABSENT(i)) { + child = BUS_ADD_CHILD(parent, 150, "cpu", i); + if (child == NULL) + panic("legacy_attach cpu"); + } +} + +static device_t +cpu_add_child(device_t bus, u_int order, const char *name, int unit) +{ + struct cpu_device *cd; + device_t child; + struct pcpu *pc; + + if ((cd = malloc(sizeof(*cd), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) + return (NULL); + + resource_list_init(&cd->cd_rl); + pc = pcpu_find(device_get_unit(bus)); + cd->cd_pcpu = pc; + + child = device_add_child_ordered(bus, order, name, unit); + if (child != NULL) { + pc->pc_device = child; + device_set_ivars(child, cd); + } else + free(cd, M_DEVBUF); + return (child); +} + +static struct resource_list * +cpu_get_rlist(device_t dev, device_t child) +{ + struct cpu_device *cpdev; + + cpdev = device_get_ivars(child); + return (&cpdev->cd_rl); +} + +static int +cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) +{ + struct cpu_device *cpdev; + + if (index != CPU_IVAR_PCPU) + return (ENOENT); + cpdev = device_get_ivars(child); + *result = (uintptr_t)cpdev->cd_pcpu; + return (0); +} diff --git a/freebsd/sys/i386/include/machine/cpufunc.h b/freebsd/sys/i386/include/machine/cpufunc.h new file mode 100644 index 00000000..093e38a4 --- /dev/null +++ b/freebsd/sys/i386/include/machine/cpufunc.h @@ -0,0 +1,761 @@ +/*- + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Functions to provide access to special i386 instructions. + * This in included in sys/systm.h, and that file should be + * used in preference to this. + */ + +#ifndef _MACHINE_CPUFUNC_HH_ +#define _MACHINE_CPUFUNC_HH_ + +#ifndef _SYS_CDEFS_HH_ +#error this file needs sys/cdefs.h as a prerequisite +#endif + +#ifdef XEN +extern void xen_cli(void); +extern void xen_sti(void); +extern u_int xen_rcr2(void); +extern void xen_load_cr3(u_int data); +extern void xen_tlb_flush(void); +extern void xen_invlpg(u_int addr); +extern void write_eflags(u_int eflags); +extern u_int read_eflags(void); +#endif + +struct region_descriptor; + +#define readb(va) (*(volatile u_int8_t *) (va)) +#define readw(va) (*(volatile u_int16_t *) (va)) +#define readl(va) (*(volatile u_int32_t *) (va)) + +#define writeb(va, d) (*(volatile u_int8_t *) (va) = (d)) +#define writew(va, d) (*(volatile u_int16_t *) (va) = (d)) +#define writel(va, d) (*(volatile u_int32_t *) (va) = (d)) + +#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE) + +#ifndef __rtems__ +static __inline void +breakpoint(void) +{ + __asm __volatile("int $3"); +} +#endif + +static __inline u_int +bsfl(u_int mask) +{ + u_int result; + + __asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); + return (result); +} + +static __inline u_int +bsrl(u_int mask) +{ + u_int result; + + __asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); + return (result); +} + +static __inline void +clflush(u_long addr) +{ + + __asm __volatile("clflush %0" : : "m" (*(char *)addr)); +} + +static __inline void +disable_intr(void) +{ +#ifdef XEN + xen_cli(); +#else + __asm __volatile("cli" : : : "memory"); +#endif +} + +static __inline void +do_cpuid(u_int ax, u_int *p) +{ + __asm __volatile("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax)); +} + +static __inline void +cpuid_count(u_int ax, u_int cx, u_int *p) +{ + __asm __volatile("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax), "c" (cx)); +} + +static __inline void +enable_intr(void) +{ +#ifdef XEN + xen_sti(); +#else + __asm __volatile("sti"); +#endif +} + +static __inline void +cpu_monitor(const void *addr, int extensions, int hints) +{ + __asm __volatile("monitor;" + : :"a" (addr), "c" (extensions), "d"(hints)); +} + +static __inline void +cpu_mwait(int extensions, int hints) +{ + __asm __volatile("mwait;" : :"a" (hints), "c" (extensions)); +} + +static __inline void +mfence(void) +{ + + __asm __volatile("mfence" : : : "memory"); +} + +#ifdef _KERNEL + +#define HAVE_INLINE_FFS + +static __inline int +ffs(int mask) +{ + /* + * Note that gcc-2's builtin ffs would be used if we didn't declare + * this inline or turn off the builtin. The builtin is faster but + * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later + * versions. + */ + return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1); +} + +#define HAVE_INLINE_FLS + +#ifndef __rtems__ +static __inline int +fls(int mask) +{ + return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); +} +#endif + +#endif /* _KERNEL */ + +static __inline void +halt(void) +{ + __asm __volatile("hlt"); +} + +static __inline u_char +inb(u_int port) +{ + u_char data; + + __asm volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); + return (data); +} + +static __inline u_int +inl(u_int port) +{ + u_int data; + + __asm volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); + return (data); +} + +static __inline void +insb(u_int port, void *addr, size_t cnt) +{ + __asm __volatile("cld; rep; insb" + : "+D" (addr), "+c" (cnt) + : "d" (port) + : "memory"); +} + +static __inline void +insw(u_int port, void *addr, size_t cnt) +{ + __asm __volatile("cld; rep; insw" + : "+D" (addr), "+c" (cnt) + : "d" (port) + : "memory"); +} + +static __inline void +insl(u_int port, void *addr, size_t cnt) +{ + __asm __volatile("cld; rep; insl" + : "+D" (addr), "+c" (cnt) + : "d" (port) + : "memory"); +} + +static __inline void +invd(void) +{ + __asm __volatile("invd"); +} + +static __inline u_short +inw(u_int port) +{ + u_short data; + + __asm volatile("inw %w1, %0" : "=a" (data) : "Nd" (port)); + return (data); +} + +static __inline void +outb(u_int port, u_char data) +{ + __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); +} + +static __inline void +outl(u_int port, u_int data) +{ + __asm volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); +} + +static __inline void +outsb(u_int port, const void *addr, size_t cnt) +{ + __asm __volatile("cld; rep; outsb" + : "+S" (addr), "+c" (cnt) + : "d" (port)); +} + +static __inline void +outsw(u_int port, const void *addr, size_t cnt) +{ + __asm __volatile("cld; rep; outsw" + : "+S" (addr), "+c" (cnt) + : "d" (port)); +} + +static __inline void +outsl(u_int port, const void *addr, size_t cnt) +{ + __asm __volatile("cld; rep; outsl" + : "+S" (addr), "+c" (cnt) + : "d" (port)); +} + +static __inline void +outw(u_int port, u_short data) +{ + __asm volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); +} + +static __inline void +ia32_pause(void) +{ + __asm __volatile("pause"); +} + +static __inline u_int +#ifdef XEN +_read_eflags(void) +#else +read_eflags(void) +#endif +{ + u_int ef; + + __asm __volatile("pushfl; popl %0" : "=r" (ef)); + return (ef); +} + +static __inline uint64_t +rdmsr(u_int msr) +{ + uint64_t rv; + + __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr)); + return (rv); +} + +static __inline uint64_t +rdpmc(u_int pmc) +{ + uint64_t rv; + + __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc)); + return (rv); +} + +static __inline uint64_t +rdtsc(void) +{ + uint64_t rv; + + __asm __volatile("rdtsc" : "=A" (rv)); + return (rv); +} + +static __inline void +wbinvd(void) +{ + __asm __volatile("wbinvd"); +} + +static __inline void +#ifdef XEN +_write_eflags(u_int ef) +#else +write_eflags(u_int ef) +#endif +{ + __asm __volatile("pushl %0; popfl" : : "r" (ef)); +} + +static __inline void +wrmsr(u_int msr, uint64_t newval) +{ + __asm __volatile("wrmsr" : : "A" (newval), "c" (msr)); +} + +static __inline void +load_cr0(u_int data) +{ + + __asm __volatile("movl %0,%%cr0" : : "r" (data)); +} + +static __inline u_int +rcr0(void) +{ + u_int data; + + __asm __volatile("movl %%cr0,%0" : "=r" (data)); + return (data); +} + +static __inline u_int +rcr2(void) +{ + u_int data; + +#ifdef XEN + return (xen_rcr2()); +#endif + __asm __volatile("movl %%cr2,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_cr3(u_int data) +{ +#ifdef XEN + xen_load_cr3(data); +#else + __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory"); +#endif +} + +static __inline u_int +rcr3(void) +{ + u_int data; + + __asm __volatile("movl %%cr3,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_cr4(u_int data) +{ + __asm __volatile("movl %0,%%cr4" : : "r" (data)); +} + +static __inline u_int +rcr4(void) +{ + u_int data; + + __asm __volatile("movl %%cr4,%0" : "=r" (data)); + return (data); +} + +/* + * Global TLB flush (except for thise for pages marked PG_G) + */ +static __inline void +invltlb(void) +{ +#ifdef XEN + xen_tlb_flush(); +#else + load_cr3(rcr3()); +#endif +} + +/* + * TLB flush for an individual page (even if it has PG_G). + * Only works on 486+ CPUs (i386 does not have PG_G). + */ +static __inline void +invlpg(u_int addr) +{ + +#ifdef XEN + xen_invlpg(addr); +#else + __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); +#endif +} + +static __inline u_int +rfs(void) +{ + u_int sel; + __asm __volatile("mov %%fs,%0" : "=rm" (sel)); + return (sel); +} + +static __inline uint64_t +rgdt(void) +{ + uint64_t gdtr; + __asm __volatile("sgdt %0" : "=m" (gdtr)); + return (gdtr); +} + +static __inline u_int +rgs(void) +{ + u_int sel; + __asm __volatile("mov %%gs,%0" : "=rm" (sel)); + return (sel); +} + +static __inline uint64_t +ridt(void) +{ + uint64_t idtr; + __asm __volatile("sidt %0" : "=m" (idtr)); + return (idtr); +} + +static __inline u_short +rldt(void) +{ + u_short ldtr; + __asm __volatile("sldt %0" : "=g" (ldtr)); + return (ldtr); +} + +static __inline u_int +rss(void) +{ + u_int sel; + __asm __volatile("mov %%ss,%0" : "=rm" (sel)); + return (sel); +} + +static __inline u_short +rtr(void) +{ + u_short tr; + __asm __volatile("str %0" : "=g" (tr)); + return (tr); +} + +static __inline void +load_fs(u_int sel) +{ + __asm __volatile("mov %0,%%fs" : : "rm" (sel)); +} + +static __inline void +load_gs(u_int sel) +{ + __asm __volatile("mov %0,%%gs" : : "rm" (sel)); +} + +static __inline void +lidt(struct region_descriptor *addr) +{ + __asm __volatile("lidt (%0)" : : "r" (addr)); +} + +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 u_int +rdr0(void) +{ + u_int data; + __asm __volatile("movl %%dr0,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr0(u_int dr0) +{ + __asm __volatile("movl %0,%%dr0" : : "r" (dr0)); +} + +static __inline u_int +rdr1(void) +{ + u_int data; + __asm __volatile("movl %%dr1,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr1(u_int dr1) +{ + __asm __volatile("movl %0,%%dr1" : : "r" (dr1)); +} + +static __inline u_int +rdr2(void) +{ + u_int data; + __asm __volatile("movl %%dr2,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr2(u_int dr2) +{ + __asm __volatile("movl %0,%%dr2" : : "r" (dr2)); +} + +static __inline u_int +rdr3(void) +{ + u_int data; + __asm __volatile("movl %%dr3,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr3(u_int dr3) +{ + __asm __volatile("movl %0,%%dr3" : : "r" (dr3)); +} + +static __inline u_int +rdr4(void) +{ + u_int data; + __asm __volatile("movl %%dr4,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr4(u_int dr4) +{ + __asm __volatile("movl %0,%%dr4" : : "r" (dr4)); +} + +static __inline u_int +rdr5(void) +{ + u_int data; + __asm __volatile("movl %%dr5,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr5(u_int dr5) +{ + __asm __volatile("movl %0,%%dr5" : : "r" (dr5)); +} + +static __inline u_int +rdr6(void) +{ + u_int data; + __asm __volatile("movl %%dr6,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr6(u_int dr6) +{ + __asm __volatile("movl %0,%%dr6" : : "r" (dr6)); +} + +static __inline u_int +rdr7(void) +{ + u_int data; + __asm __volatile("movl %%dr7,%0" : "=r" (data)); + return (data); +} + +static __inline void +load_dr7(u_int dr7) +{ + __asm __volatile("movl %0,%%dr7" : : "r" (dr7)); +} + +static __inline u_char +read_cyrix_reg(u_char reg) +{ + outb(0x22, reg); + return inb(0x23); +} + +static __inline void +write_cyrix_reg(u_char reg, u_char data) +{ + outb(0x22, reg); + outb(0x23, data); +} + +static __inline register_t +intr_disable(void) +{ + register_t eflags; + + eflags = read_eflags(); + disable_intr(); + return (eflags); +} + +static __inline void +intr_restore(register_t eflags) +{ + write_eflags(eflags); +} + +#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ + +#ifndef __rtems__ +int breakpoint(void); +#endif +u_int bsfl(u_int mask); +u_int bsrl(u_int mask); +void disable_intr(void); +void do_cpuid(u_int ax, u_int *p); +void enable_intr(void); +void halt(void); +void ia32_pause(void); +u_char inb(u_int port); +u_int inl(u_int port); +void insb(u_int port, void *addr, size_t cnt); +void insl(u_int port, void *addr, size_t cnt); +void insw(u_int port, void *addr, size_t cnt); +register_t intr_disable(void); +void intr_restore(register_t ef); +void invd(void); +void invlpg(u_int addr); +void invltlb(void); +u_short inw(u_int port); +void lidt(struct region_descriptor *addr); +void lldt(u_short sel); +void load_cr0(u_int cr0); +void load_cr3(u_int cr3); +void load_cr4(u_int cr4); +void load_dr0(u_int dr0); +void load_dr1(u_int dr1); +void load_dr2(u_int dr2); +void load_dr3(u_int dr3); +void load_dr4(u_int dr4); +void load_dr5(u_int dr5); +void load_dr6(u_int dr6); +void load_dr7(u_int dr7); +void load_fs(u_int sel); +void load_gs(u_int sel); +void ltr(u_short sel); +void outb(u_int port, u_char data); +void outl(u_int port, u_int data); +void outsb(u_int port, const void *addr, size_t cnt); +void outsl(u_int port, const void *addr, size_t cnt); +void outsw(u_int port, const void *addr, size_t cnt); +void outw(u_int port, u_short data); +u_int rcr0(void); +u_int rcr2(void); +u_int rcr3(void); +u_int rcr4(void); +uint64_t rdmsr(u_int msr); +uint64_t rdpmc(u_int pmc); +u_int rdr0(void); +u_int rdr1(void); +u_int rdr2(void); +u_int rdr3(void); +u_int rdr4(void); +u_int rdr5(void); +u_int rdr6(void); +u_int rdr7(void); +uint64_t rdtsc(void); +u_char read_cyrix_reg(u_char reg); +u_int read_eflags(void); +u_int rfs(void); +uint64_t rgdt(void); +u_int rgs(void); +uint64_t ridt(void); +u_short rldt(void); +u_short rtr(void); +void wbinvd(void); +void write_cyrix_reg(u_char reg, u_char data); +void write_eflags(u_int ef); +void wrmsr(u_int msr, uint64_t newval); + +#endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ + +void reset_dbregs(void); + +#ifdef _KERNEL +int rdmsr_safe(u_int msr, uint64_t *val); +int wrmsr_safe(u_int msr, uint64_t newval); +#endif + +#endif /* !_MACHINE_CPUFUNC_HH_ */ diff --git a/freebsd/sys/i386/include/machine/in_cksum.h b/freebsd/sys/i386/include/machine/in_cksum.h new file mode 100644 index 00000000..c121f46d --- /dev/null +++ b/freebsd/sys/i386/include/machine/in_cksum.h @@ -0,0 +1,171 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/*- + * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from tahoe: in_cksum.c 1.2 86/01/05 + * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 + * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp + * from: FreeBSD: src/sys/alpha/include/in_cksum.h,v 1.5 2000/05/06 + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_IN_CKSUM_HH_ +#define _MACHINE_IN_CKSUM_HH_ 1 + +#include <freebsd/sys/cdefs.h> + +#define in_cksum(m, len) in_cksum_skip(m, len, 0) + +static __inline void +in_cksum_update(struct ip *ip) +{ + int __tmp; + + __tmp = (int)ip->ip_sum + 1; + ip->ip_sum = __tmp + (__tmp >> 16); +} + +static __inline u_short +in_addword(u_short sum, u_short b) +{ + u_long __ret, __tmp; + + __asm( + "sll %2, 16, %0\n" + "sll %3, 16, %1\n" + "addcc %0, %1, %0\n" + "srl %0, 16, %0\n" + "addc %0, 0, %0\n" + : "=&r" (__ret), "=&r" (__tmp) : "r" (sum), "r" (b) : "cc"); + return (__ret); +} + +static __inline u_short +in_pseudo(u_int sum, u_int b, u_int c) +{ + u_long __tmp; + + __asm( + "addcc %0, %3, %0\n" + "addccc %0, %4, %0\n" + "addc %0, 0, %0\n" + "sll %0, 16, %1\n" + "addcc %0, %1, %0\n" + "srl %0, 16, %0\n" + "addc %0, 0, %0\n" + : "=r" (sum), "=&r" (__tmp) : "0" (sum), "r" (b), "r" (c) : "cc"); + return (sum); +} + +static __inline u_int +in_cksum_hdr(struct ip *ip) +{ + u_long __ret, __tmp1, __tmp2, __tmp3, __tmp4; + + /* + * Use 32-bit memory accesses and additions - addition with carry only + * works for 32 bits, and fixing up alignment issues for 64 is probably + * more trouble than it's worth. + * This may read outside of the ip header, but does not cross a page + * boundary in doing so, so that should be OK. + * Actually, this specialized implementation might be overkill - using + * a generic implementation for both in_cksum_skip and in_cksum_hdr + * should not be too much more expensive. + */ +#define __LD_ADD(addr, tmp, sum, offs, mod) \ + "lduw [" #addr " + " #offs "], " #tmp "\n" \ + "add" # mod " " #sum ", " #tmp ", " #sum "\n" + + __asm( + "and %5, 3, %3\n" + "andn %5, 3, %1\n" + "brz,pt %3, 0f\n" + " lduw [%1], %0\n" + "mov 4, %4\n" + "sub %4, %3, %4\n" + "sll %4, 3, %4\n" /* fix up unaligned buffers */ + "mov 1, %2\n" + "sll %2, %4, %4\n" + "sub %4, 1, %4\n" + "lduw [%1 + 20], %2\n" + "andn %2, %4, %2\n" + "and %0, %4, %0\n" + "or %0, %2, %0\n" + "0:\n" + __LD_ADD(%1, %2, %0, 4, cc) + __LD_ADD(%1, %2, %0, 8, ccc) + __LD_ADD(%1, %2, %0, 12, ccc) + __LD_ADD(%1, %2, %0, 16, ccc) + "addc %0, 0, %0\n" /* reduce */ + "1:\n" + "sll %0, 16, %2\n" + "addcc %0, %2, %0\n" + "srl %0, 16, %0\n" + "addc %0, 0, %0\n" + "andcc %3, 1, %3\n" /* need to byte-swap? */ + "clr %3\n" + "bne,a,pn %%xcc, 1b\n" + " sll %0, 8, %0\n" + "not %0\n" + "sll %0, 16, %0\n" + "srl %0, 16, %0\n" + : "=&r" (__ret), "=r" (__tmp1), "=&r" (__tmp2), "=&r" (__tmp3), + "=&r" (__tmp4) : "1" (ip) : "cc"); +#undef __LD_ADD + return (__ret); +} + +#ifdef _KERNEL +u_short in_cksum_skip(struct mbuf *m, int len, int skip); +#endif + +#endif /* _MACHINE_IN_CKSUM_HH_ */ diff --git a/freebsd/sys/i386/include/machine/intr_machdep.h b/freebsd/sys/i386/include/machine/intr_machdep.h new file mode 100644 index 00000000..0dbef09d --- /dev/null +++ b/freebsd/sys/i386/include/machine/intr_machdep.h @@ -0,0 +1,161 @@ +/*- + * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __MACHINE_INTR_MACHDEP_HH__ +#define __MACHINE_INTR_MACHDEP_HH__ + +#ifdef _KERNEL + +/* + * The maximum number of I/O interrupts we allow. This number is rather + * arbitrary as it is just the maximum IRQ resource value. The interrupt + * source for a given IRQ maps that I/O interrupt to device interrupt + * source whether it be a pin on an interrupt controller or an MSI interrupt. + * The 16 ISA IRQs are assigned fixed IDT vectors, but all other device + * interrupts allocate IDT vectors on demand. Currently we have 191 IDT + * vectors available for device interrupts. On many systems with I/O APICs, + * a lot of the IRQs are not used, so this number can be much larger than + * 191 and still be safe since only interrupt sources in actual use will + * allocate IDT vectors. + * + * The first 255 IRQs (0 - 254) are reserved for ISA IRQs and PCI intline IRQs. + * IRQ values beyond 256 are used by MSI. We leave 255 unused to avoid + * confusion since 255 is used in PCI to indicate an invalid IRQ. + */ +#define NUM_MSI_INTS 512 +#define FIRST_MSI_INT 256 +#define NUM_IO_INTS (FIRST_MSI_INT + NUM_MSI_INTS) + +/* + * Default base address for MSI messages on x86 platforms. + */ +#define MSI_INTEL_ADDR_BASE 0xfee00000 + +/* + * - 1 ??? dummy counter. + * - 2 counters for each I/O interrupt. + * - 1 counter for each CPU for lapic timer. + * - 7 counters for each CPU for IPI counters for SMP. + */ +#ifdef SMP +#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 7) * MAXCPU) +#else +#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1) +#endif + +#ifndef LOCORE + +typedef void inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); + +#define IDTVEC(name) __CONCAT(X,name) + +struct intsrc; + +/* + * Methods that a PIC provides to mask/unmask a given interrupt source, + * "turn on" the interrupt on the CPU side by setting up an IDT entry, and + * return the vector associated with this source. + */ +struct pic { + void (*pic_enable_source)(struct intsrc *); + void (*pic_disable_source)(struct intsrc *, int); + void (*pic_eoi_source)(struct intsrc *); + void (*pic_enable_intr)(struct intsrc *); + void (*pic_disable_intr)(struct intsrc *); + int (*pic_vector)(struct intsrc *); + int (*pic_source_pending)(struct intsrc *); + void (*pic_suspend)(struct pic *); + void (*pic_resume)(struct pic *); + int (*pic_config_intr)(struct intsrc *, enum intr_trigger, + enum intr_polarity); + int (*pic_assign_cpu)(struct intsrc *, u_int apic_id); + STAILQ_ENTRY(pic) pics; +}; + +/* Flags for pic_disable_source() */ +enum { + PIC_EOI, + PIC_NO_EOI, +}; + +/* + * An interrupt source. The upper-layer code uses the PIC methods to + * control a given source. The lower-layer PIC drivers can store additional + * private data in a given interrupt source such as an interrupt pin number + * or an I/O APIC pointer. + */ +struct intsrc { + struct pic *is_pic; + struct intr_event *is_event; + u_long *is_count; + u_long *is_straycount; + u_int is_index; + u_int is_handlers; +}; + +struct trapframe; + +extern struct mtx icu_lock; +extern int elcr_found; + +/* XXX: The elcr_* prototypes probably belong somewhere else. */ +int elcr_probe(void); +enum intr_trigger elcr_read_trigger(u_int irq); +void elcr_resume(void); +void elcr_write_trigger(u_int irq, enum intr_trigger trigger); +#ifdef SMP +void intr_add_cpu(u_int cpu); +#endif +int intr_add_handler(const char *name, int vector, driver_filter_t filter, + driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep); +#ifdef SMP +int intr_bind(u_int vector, u_char cpu); +#endif +int intr_config_intr(int vector, enum intr_trigger trig, + enum intr_polarity pol); +int intr_describe(u_int vector, void *ih, const char *descr); +void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame); +u_int intr_next_cpu(void); +struct intsrc *intr_lookup_source(int vector); +int intr_register_pic(struct pic *pic); +int intr_register_source(struct intsrc *isrc); +int intr_remove_handler(void *cookie); +void intr_resume(void); +void intr_suspend(void); +void intrcnt_add(const char *name, u_long **countp); +void nexus_add_irq(u_long irq); +int msi_alloc(device_t dev, int count, int maxcount, int *irqs); +void msi_init(void); +int msi_map(int irq, uint64_t *addr, uint32_t *data); +int msi_release(int* irqs, int count); +int msix_alloc(device_t dev, int *irq); +int msix_release(int irq); + +#endif /* !LOCORE */ +#endif /* _KERNEL */ +#endif /* !__MACHINE_INTR_MACHDEP_HH__ */ diff --git a/freebsd/sys/i386/include/machine/md_var.h b/freebsd/sys/i386/include/machine/md_var.h new file mode 100644 index 00000000..43bd0491 --- /dev/null +++ b/freebsd/sys/i386/include/machine/md_var.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 1995 Bruce D. Evans. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MD_VAR_HH_ +#define _MACHINE_MD_VAR_HH_ + +/* + * Miscellaneous machine-dependent declarations. + */ + +extern long Maxmem; +extern u_int basemem; /* PA of original top of base memory */ +extern int busdma_swi_pending; +extern u_int cpu_exthigh; +extern u_int cpu_feature; +extern u_int cpu_feature2; +extern u_int amd_feature; +extern u_int amd_feature2; +extern u_int amd_pminfo; +extern u_int via_feature_rng; +extern u_int via_feature_xcrypt; +extern u_int cpu_clflush_line_size; +extern u_int cpu_fxsr; +extern u_int cpu_high; +extern u_int cpu_id; +extern u_int cpu_mxcsr_mask; +extern u_int cpu_procinfo; +extern u_int cpu_procinfo2; +extern char cpu_vendor[]; +extern u_int cpu_vendor_id; +extern u_int cyrix_did; +extern char kstack[]; +extern char sigcode[]; +extern int szsigcode; +#ifdef COMPAT_FREEBSD4 +extern int szfreebsd4_sigcode; +#endif +#ifdef COMPAT_43 +extern int szosigcode; +#endif +extern uint32_t *vm_page_dump; +extern int vm_page_dump_size; +extern int workaround_erratum383; + +typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); +struct thread; +struct reg; +struct fpreg; +struct dbreg; +struct dumperinfo; + +void bcopyb(const void *from, void *to, size_t len); +void busdma_swi(void); +void cpu_setregs(void); +void cpu_switch_load_gs(void) __asm(__STRING(cpu_switch_load_gs)); +void doreti_iret(void) __asm(__STRING(doreti_iret)); +void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault)); +void doreti_popl_ds(void) __asm(__STRING(doreti_popl_ds)); +void doreti_popl_ds_fault(void) __asm(__STRING(doreti_popl_ds_fault)); +void doreti_popl_es(void) __asm(__STRING(doreti_popl_es)); +void doreti_popl_es_fault(void) __asm(__STRING(doreti_popl_es_fault)); +void doreti_popl_fs(void) __asm(__STRING(doreti_popl_fs)); +void doreti_popl_fs_fault(void) __asm(__STRING(doreti_popl_fs_fault)); +void dump_add_page(vm_paddr_t); +void dump_drop_page(vm_paddr_t); +void enable_sse(void); +void fillw(int /*u_short*/ pat, void *base, size_t cnt); +void i686_pagezero(void *addr); +void sse2_pagezero(void *addr); +void init_AMD_Elan_sc520(void); +int is_physical_memory(vm_paddr_t addr); +int isa_nmi(int cd); +vm_paddr_t kvtop(void *addr); +void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int selec); +int user_dbreg_trap(void); +void minidumpsys(struct dumperinfo *); + +#endif /* !_MACHINE_MD_VAR_HH_ */ diff --git a/freebsd/sys/i386/include/machine/specialreg.h b/freebsd/sys/i386/include/machine/specialreg.h new file mode 100644 index 00000000..4cbd0ec2 --- /dev/null +++ b/freebsd/sys/i386/include/machine/specialreg.h @@ -0,0 +1,596 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + * $FreeBSD$ + */ + +#ifndef _MACHINE_SPECIALREG_HH_ +#define _MACHINE_SPECIALREG_HH_ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" (fpu) Present */ +#define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in + all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * Bits in PPro special registers + */ +#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */ +#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */ +#define CR4_TSD 0x00000004 /* Time stamp disable */ +#define CR4_DE 0x00000008 /* Debugging extensions */ +#define CR4_PSE 0x00000010 /* Page size extensions */ +#define CR4_PAE 0x00000020 /* Physical address extension */ +#define CR4_MCE 0x00000040 /* Machine check enable */ +#define CR4_PGE 0x00000080 /* Page global enable */ +#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */ +#define CR4_FXSR 0x00000200 /* Fast FPU save/restore used by OS */ +#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */ + +/* + * Bits in AMD64 special registers. EFER is 64 bits wide. + */ +#define EFER_NXE 0x000000800 /* PTE No-Execute bit enable (R/W) */ + +/* + * CPUID instruction features register + */ +#define CPUID_FPU 0x00000001 +#define CPUID_VME 0x00000002 +#define CPUID_DE 0x00000004 +#define CPUID_PSE 0x00000008 +#define CPUID_TSC 0x00000010 +#define CPUID_MSR 0x00000020 +#define CPUID_PAE 0x00000040 +#define CPUID_MCE 0x00000080 +#define CPUID_CX8 0x00000100 +#define CPUID_APIC 0x00000200 +#define CPUID_B10 0x00000400 +#define CPUID_SEP 0x00000800 +#define CPUID_MTRR 0x00001000 +#define CPUID_PGE 0x00002000 +#define CPUID_MCA 0x00004000 +#define CPUID_CMOV 0x00008000 +#define CPUID_PAT 0x00010000 +#define CPUID_PSE36 0x00020000 +#define CPUID_PSN 0x00040000 +#define CPUID_CLFSH 0x00080000 +#define CPUID_B20 0x00100000 +#define CPUID_DS 0x00200000 +#define CPUID_ACPI 0x00400000 +#define CPUID_MMX 0x00800000 +#define CPUID_FXSR 0x01000000 +#define CPUID_SSE 0x02000000 +#define CPUID_XMM 0x02000000 +#define CPUID_SSE2 0x04000000 +#define CPUID_SS 0x08000000 +#define CPUID_HTT 0x10000000 +#define CPUID_TM 0x20000000 +#define CPUID_IA64 0x40000000 +#define CPUID_PBE 0x80000000 + +#define CPUID2_SSE3 0x00000001 +#define CPUID2_PCLMULQDQ 0x00000002 +#define CPUID2_DTES64 0x00000004 +#define CPUID2_MON 0x00000008 +#define CPUID2_DS_CPL 0x00000010 +#define CPUID2_VMX 0x00000020 +#define CPUID2_SMX 0x00000040 +#define CPUID2_EST 0x00000080 +#define CPUID2_TM2 0x00000100 +#define CPUID2_SSSE3 0x00000200 +#define CPUID2_CNXTID 0x00000400 +#define CPUID2_CX16 0x00002000 +#define CPUID2_XTPR 0x00004000 +#define CPUID2_PDCM 0x00008000 +#define CPUID2_PCID 0x00020000 +#define CPUID2_DCA 0x00040000 +#define CPUID2_SSE41 0x00080000 +#define CPUID2_SSE42 0x00100000 +#define CPUID2_X2APIC 0x00200000 +#define CPUID2_MOVBE 0x00400000 +#define CPUID2_POPCNT 0x00800000 +#define CPUID2_AESNI 0x02000000 + +/* + * Important bits in the AMD extended cpuid flags + */ +#define AMDID_SYSCALL 0x00000800 +#define AMDID_MP 0x00080000 +#define AMDID_NX 0x00100000 +#define AMDID_EXT_MMX 0x00400000 +#define AMDID_FFXSR 0x01000000 +#define AMDID_PAGE1GB 0x04000000 +#define AMDID_RDTSCP 0x08000000 +#define AMDID_LM 0x20000000 +#define AMDID_EXT_3DNOW 0x40000000 +#define AMDID_3DNOW 0x80000000 + +#define AMDID2_LAHF 0x00000001 +#define AMDID2_CMP 0x00000002 +#define AMDID2_SVM 0x00000004 +#define AMDID2_EXT_APIC 0x00000008 +#define AMDID2_CR8 0x00000010 +#define AMDID2_ABM 0x00000020 +#define AMDID2_SSE4A 0x00000040 +#define AMDID2_MAS 0x00000080 +#define AMDID2_PREFETCH 0x00000100 +#define AMDID2_OSVW 0x00000200 +#define AMDID2_IBS 0x00000400 +#define AMDID2_SSE5 0x00000800 +#define AMDID2_SKINIT 0x00001000 +#define AMDID2_WDT 0x00002000 + +/* + * CPUID instruction 1 eax info + */ +#define CPUID_STEPPING 0x0000000f +#define CPUID_MODEL 0x000000f0 +#define CPUID_FAMILY 0x00000f00 +#define CPUID_EXT_MODEL 0x000f0000 +#define CPUID_EXT_FAMILY 0x0ff00000 +#define CPUID_TO_MODEL(id) \ + ((((id) & CPUID_MODEL) >> 4) | \ + ((((id) & CPUID_FAMILY) >= 0x600) ? \ + (((id) & CPUID_EXT_MODEL) >> 12) : 0)) +#define CPUID_TO_FAMILY(id) \ + ((((id) & CPUID_FAMILY) >> 8) + \ + ((((id) & CPUID_FAMILY) == 0xf00) ? \ + (((id) & CPUID_EXT_FAMILY) >> 20) : 0)) + +/* + * CPUID instruction 1 ebx info + */ +#define CPUID_BRAND_INDEX 0x000000ff +#define CPUID_CLFUSH_SIZE 0x0000ff00 +#define CPUID_HTT_CORES 0x00ff0000 +#define CPUID_LOCAL_APIC_ID 0xff000000 + +/* + * CPUID instruction 0xb ebx info. + */ +#define CPUID_TYPE_INVAL 0 +#define CPUID_TYPE_SMT 1 +#define CPUID_TYPE_CORE 2 + +/* + * AMD extended function 8000_0007h edx info + */ +#define AMDPM_TS 0x00000001 +#define AMDPM_FID 0x00000002 +#define AMDPM_VID 0x00000004 +#define AMDPM_TTP 0x00000008 +#define AMDPM_TM 0x00000010 +#define AMDPM_STC 0x00000020 +#define AMDPM_100MHZ_STEPS 0x00000040 +#define AMDPM_HW_PSTATE 0x00000080 +#define AMDPM_TSC_INVARIANT 0x00000100 + +/* + * AMD extended function 8000_0008h ecx info + */ +#define AMDID_CMP_CORES 0x000000ff + +/* + * CPUID manufacturers identifiers + */ +#define AMD_VENDOR_ID "AuthenticAMD" +#define CENTAUR_VENDOR_ID "CentaurHauls" +#define CYRIX_VENDOR_ID "CyrixInstead" +#define INTEL_VENDOR_ID "GenuineIntel" +#define NEXGEN_VENDOR_ID "NexGenDriven" +#define NSC_VENDOR_ID "Geode by NSC" +#define RISE_VENDOR_ID "RiseRiseRise" +#define SIS_VENDOR_ID "SiS SiS SiS " +#define TRANSMETA_VENDOR_ID "GenuineTMx86" +#define UMC_VENDOR_ID "UMC UMC UMC " + +/* + * Model-specific registers for the i386 family + */ +#define MSR_P5_MC_ADDR 0x000 +#define MSR_P5_MC_TYPE 0x001 +#define MSR_TSC 0x010 +#define MSR_P5_CESR 0x011 +#define MSR_P5_CTR0 0x012 +#define MSR_P5_CTR1 0x013 +#define MSR_IA32_PLATFORM_ID 0x017 +#define MSR_APICBASE 0x01b +#define MSR_EBL_CR_POWERON 0x02a +#define MSR_TEST_CTL 0x033 +#define MSR_BIOS_UPDT_TRIG 0x079 +#define MSR_BBL_CR_D0 0x088 +#define MSR_BBL_CR_D1 0x089 +#define MSR_BBL_CR_D2 0x08a +#define MSR_BIOS_SIGN 0x08b +#define MSR_PERFCTR0 0x0c1 +#define MSR_PERFCTR1 0x0c2 +#define MSR_IA32_EXT_CONFIG 0x0ee /* Undocumented. Core Solo/Duo only */ +#define MSR_MTRRcap 0x0fe +#define MSR_BBL_CR_ADDR 0x116 +#define MSR_BBL_CR_DECC 0x118 +#define MSR_BBL_CR_CTL 0x119 +#define MSR_BBL_CR_TRIG 0x11a +#define MSR_BBL_CR_BUSY 0x11b +#define MSR_BBL_CR_CTL3 0x11e +#define MSR_SYSENTER_CS_MSR 0x174 +#define MSR_SYSENTER_ESP_MSR 0x175 +#define MSR_SYSENTER_EIP_MSR 0x176 +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MCG_CTL 0x17b +#define MSR_EVNTSEL0 0x186 +#define MSR_EVNTSEL1 0x187 +#define MSR_THERM_CONTROL 0x19a +#define MSR_THERM_INTERRUPT 0x19b +#define MSR_THERM_STATUS 0x19c +#define MSR_IA32_MISC_ENABLE 0x1a0 +#define MSR_IA32_TEMPERATURE_TARGET 0x1a2 +#define MSR_DEBUGCTLMSR 0x1d9 +#define MSR_LASTBRANCHFROMIP 0x1db +#define MSR_LASTBRANCHTOIP 0x1dc +#define MSR_LASTINTFROMIP 0x1dd +#define MSR_LASTINTTOIP 0x1de +#define MSR_ROB_CR_BKUPTMPDR6 0x1e0 +#define MSR_MTRRVarBase 0x200 +#define MSR_MTRR64kBase 0x250 +#define MSR_MTRR16kBase 0x258 +#define MSR_MTRR4kBase 0x268 +#define MSR_PAT 0x277 +#define MSR_MC0_CTL2 0x280 +#define MSR_MTRRdefType 0x2ff +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 +#define MSR_MC1_CTL 0x404 +#define MSR_MC1_STATUS 0x405 +#define MSR_MC1_ADDR 0x406 +#define MSR_MC1_MISC 0x407 +#define MSR_MC2_CTL 0x408 +#define MSR_MC2_STATUS 0x409 +#define MSR_MC2_ADDR 0x40a +#define MSR_MC2_MISC 0x40b +#define MSR_MC3_CTL 0x40c +#define MSR_MC3_STATUS 0x40d +#define MSR_MC3_ADDR 0x40e +#define MSR_MC3_MISC 0x40f +#define MSR_MC4_CTL 0x410 +#define MSR_MC4_STATUS 0x411 +#define MSR_MC4_ADDR 0x412 +#define MSR_MC4_MISC 0x413 + +/* + * Constants related to MSR's. + */ +#define APICBASE_RESERVED 0x000006ff +#define APICBASE_BSP 0x00000100 +#define APICBASE_ENABLED 0x00000800 +#define APICBASE_ADDRESS 0xfffff000 + +/* + * PAT modes. + */ +#define PAT_UNCACHEABLE 0x00 +#define PAT_WRITE_COMBINING 0x01 +#define PAT_WRITE_THROUGH 0x04 +#define PAT_WRITE_PROTECTED 0x05 +#define PAT_WRITE_BACK 0x06 +#define PAT_UNCACHED 0x07 +#define PAT_VALUE(i, m) ((long long)(m) << (8 * (i))) +#define PAT_MASK(i) PAT_VALUE(i, 0xff) + +/* + * Constants related to MTRRs + */ +#define MTRR_UNCACHEABLE 0x00 +#define MTRR_WRITE_COMBINING 0x01 +#define MTRR_WRITE_THROUGH 0x04 +#define MTRR_WRITE_PROTECTED 0x05 +#define MTRR_WRITE_BACK 0x06 +#define MTRR_N64K 8 /* numbers of fixed-size entries */ +#define MTRR_N16K 16 +#define MTRR_N4K 64 +#define MTRR_CAP_WC 0x0000000000000400 +#define MTRR_CAP_FIXED 0x0000000000000100 +#define MTRR_CAP_VCNT 0x00000000000000ff +#define MTRR_DEF_ENABLE 0x0000000000000800 +#define MTRR_DEF_FIXED_ENABLE 0x0000000000000400 +#define MTRR_DEF_TYPE 0x00000000000000ff +#define MTRR_PHYSBASE_PHYSBASE 0x000ffffffffff000 +#define MTRR_PHYSBASE_TYPE 0x00000000000000ff +#define MTRR_PHYSMASK_PHYSMASK 0x000ffffffffff000 +#define MTRR_PHYSMASK_VALID 0x0000000000000800 + +/* + * Cyrix configuration registers, accessible as IO ports. + */ +#define CCR0 0xc0 /* Configuration control register 0 */ +#define CCR0_NC0 0x01 /* First 64K of each 1M memory region is + non-cacheable */ +#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */ +#define CCR0_A20M 0x04 /* Enables A20M# input pin */ +#define CCR0_KEN 0x08 /* Enables KEN# input pin */ +#define CCR0_FLUSH 0x10 /* Enables FLUSH# input pin */ +#define CCR0_BARB 0x20 /* Flushes internal cache when entering hold + state */ +#define CCR0_CO 0x40 /* Cache org: 1=direct mapped, 0=2x set + assoc */ +#define CCR0_SUSPEND 0x80 /* Enables SUSP# and SUSPA# pins */ + +#define CCR1 0xc1 /* Configuration control register 1 */ +#define CCR1_RPL 0x01 /* Enables RPLSET and RPLVAL# pins */ +#define CCR1_SMI 0x02 /* Enables SMM pins */ +#define CCR1_SMAC 0x04 /* System management memory access */ +#define CCR1_MMAC 0x08 /* Main memory access */ +#define CCR1_NO_LOCK 0x10 /* Negate LOCK# */ +#define CCR1_SM3 0x80 /* SMM address space address region 3 */ + +#define CCR2 0xc2 +#define CCR2_WB 0x02 /* Enables WB cache interface pins */ +#define CCR2_SADS 0x02 /* Slow ADS */ +#define CCR2_LOCK_NW 0x04 /* LOCK NW Bit */ +#define CCR2_SUSP_HLT 0x08 /* Suspend on HALT */ +#define CCR2_WT1 0x10 /* WT region 1 */ +#define CCR2_WPR1 0x10 /* Write-protect region 1 */ +#define CCR2_BARB 0x20 /* Flushes write-back cache when entering + hold state. */ +#define CCR2_BWRT 0x40 /* Enables burst write cycles */ +#define CCR2_USE_SUSP 0x80 /* Enables suspend pins */ + +#define CCR3 0xc3 +#define CCR3_SMILOCK 0x01 /* SMM register lock */ +#define CCR3_NMI 0x02 /* Enables NMI during SMM */ +#define CCR3_LINBRST 0x04 /* Linear address burst cycles */ +#define CCR3_SMMMODE 0x08 /* SMM Mode */ +#define CCR3_MAPEN0 0x10 /* Enables Map0 */ +#define CCR3_MAPEN1 0x20 /* Enables Map1 */ +#define CCR3_MAPEN2 0x40 /* Enables Map2 */ +#define CCR3_MAPEN3 0x80 /* Enables Map3 */ + +#define CCR4 0xe8 +#define CCR4_IOMASK 0x07 +#define CCR4_MEM 0x08 /* Enables momory bypassing */ +#define CCR4_DTE 0x10 /* Enables directory table entry cache */ +#define CCR4_FASTFPE 0x20 /* Fast FPU exception */ +#define CCR4_CPUID 0x80 /* Enables CPUID instruction */ + +#define CCR5 0xe9 +#define CCR5_WT_ALLOC 0x01 /* Write-through allocate */ +#define CCR5_SLOP 0x02 /* LOOP instruction slowed down */ +#define CCR5_LBR1 0x10 /* Local bus region 1 */ +#define CCR5_ARREN 0x20 /* Enables ARR region */ + +#define CCR6 0xea + +#define CCR7 0xeb + +/* Performance Control Register (5x86 only). */ +#define PCR0 0x20 +#define PCR0_RSTK 0x01 /* Enables return stack */ +#define PCR0_BTB 0x02 /* Enables branch target buffer */ +#define PCR0_LOOP 0x04 /* Enables loop */ +#define PCR0_AIS 0x08 /* Enables all instrcutions stalled to + serialize pipe. */ +#define PCR0_MLR 0x10 /* Enables reordering of misaligned loads */ +#define PCR0_BTBRT 0x40 /* Enables BTB test register. */ +#define PCR0_LSSER 0x80 /* Disable reorder */ + +/* Device Identification Registers */ +#define DIR0 0xfe +#define DIR1 0xff + +/* + * Machine Check register constants. + */ +#define MCG_CAP_COUNT 0x000000ff +#define MCG_CAP_CTL_P 0x00000100 +#define MCG_CAP_EXT_P 0x00000200 +#define MCG_CAP_CMCI_P 0x00000400 +#define MCG_CAP_TES_P 0x00000800 +#define MCG_CAP_EXT_CNT 0x00ff0000 +#define MCG_CAP_SER_P 0x01000000 +#define MCG_STATUS_RIPV 0x00000001 +#define MCG_STATUS_EIPV 0x00000002 +#define MCG_STATUS_MCIP 0x00000004 +#define MCG_CTL_ENABLE 0xffffffffffffffff +#define MCG_CTL_DISABLE 0x0000000000000000 +#define MSR_MC_CTL(x) (MSR_MC0_CTL + (x) * 4) +#define MSR_MC_STATUS(x) (MSR_MC0_STATUS + (x) * 4) +#define MSR_MC_ADDR(x) (MSR_MC0_ADDR + (x) * 4) +#define MSR_MC_MISC(x) (MSR_MC0_MISC + (x) * 4) +#define MSR_MC_CTL2(x) (MSR_MC0_CTL2 + (x)) /* If MCG_CAP_CMCI_P */ +#define MC_STATUS_MCA_ERROR 0x000000000000ffff +#define MC_STATUS_MODEL_ERROR 0x00000000ffff0000 +#define MC_STATUS_OTHER_INFO 0x01ffffff00000000 +#define MC_STATUS_COR_COUNT 0x001fffc000000000 /* If MCG_CAP_CMCI_P */ +#define MC_STATUS_TES_STATUS 0x0060000000000000 /* If MCG_CAP_TES_P */ +#define MC_STATUS_AR 0x0080000000000000 /* If MCG_CAP_TES_P */ +#define MC_STATUS_S 0x0100000000000000 /* If MCG_CAP_TES_P */ +#define MC_STATUS_PCC 0x0200000000000000 +#define MC_STATUS_ADDRV 0x0400000000000000 +#define MC_STATUS_MISCV 0x0800000000000000 +#define MC_STATUS_EN 0x1000000000000000 +#define MC_STATUS_UC 0x2000000000000000 +#define MC_STATUS_OVER 0x4000000000000000 +#define MC_STATUS_VAL 0x8000000000000000 +#define MC_MISC_RA_LSB 0x000000000000003f /* If MCG_CAP_SER_P */ +#define MC_MISC_ADDRESS_MODE 0x00000000000001c0 /* If MCG_CAP_SER_P */ +#define MC_CTL2_THRESHOLD 0x0000000000007fff +#define MC_CTL2_CMCI_EN 0x0000000040000000 + +/* + * The following four 3-byte registers control the non-cacheable regions. + * These registers must be written as three separate bytes. + * + * NCRx+0: A31-A24 of starting address + * NCRx+1: A23-A16 of starting address + * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx. + * + * The non-cacheable region's starting address must be aligned to the + * size indicated by the NCR_SIZE_xx field. + */ +#define NCR1 0xc4 +#define NCR2 0xc7 +#define NCR3 0xca +#define NCR4 0xcd + +#define NCR_SIZE_0K 0 +#define NCR_SIZE_4K 1 +#define NCR_SIZE_8K 2 +#define NCR_SIZE_16K 3 +#define NCR_SIZE_32K 4 +#define NCR_SIZE_64K 5 +#define NCR_SIZE_128K 6 +#define NCR_SIZE_256K 7 +#define NCR_SIZE_512K 8 +#define NCR_SIZE_1M 9 +#define NCR_SIZE_2M 10 +#define NCR_SIZE_4M 11 +#define NCR_SIZE_8M 12 +#define NCR_SIZE_16M 13 +#define NCR_SIZE_32M 14 +#define NCR_SIZE_4G 15 + +/* + * The address region registers are used to specify the location and + * size for the eight address regions. + * + * ARRx + 0: A31-A24 of start address + * ARRx + 1: A23-A16 of start address + * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx + */ +#define ARR0 0xc4 +#define ARR1 0xc7 +#define ARR2 0xca +#define ARR3 0xcd +#define ARR4 0xd0 +#define ARR5 0xd3 +#define ARR6 0xd6 +#define ARR7 0xd9 + +#define ARR_SIZE_0K 0 +#define ARR_SIZE_4K 1 +#define ARR_SIZE_8K 2 +#define ARR_SIZE_16K 3 +#define ARR_SIZE_32K 4 +#define ARR_SIZE_64K 5 +#define ARR_SIZE_128K 6 +#define ARR_SIZE_256K 7 +#define ARR_SIZE_512K 8 +#define ARR_SIZE_1M 9 +#define ARR_SIZE_2M 10 +#define ARR_SIZE_4M 11 +#define ARR_SIZE_8M 12 +#define ARR_SIZE_16M 13 +#define ARR_SIZE_32M 14 +#define ARR_SIZE_4G 15 + +/* + * The region control registers specify the attributes associated with + * the ARRx addres regions. + */ +#define RCR0 0xdc +#define RCR1 0xdd +#define RCR2 0xde +#define RCR3 0xdf +#define RCR4 0xe0 +#define RCR5 0xe1 +#define RCR6 0xe2 +#define RCR7 0xe3 + +#define RCR_RCD 0x01 /* Disables caching for ARRx (x = 0-6). */ +#define RCR_RCE 0x01 /* Enables caching for ARR7. */ +#define RCR_WWO 0x02 /* Weak write ordering. */ +#define RCR_WL 0x04 /* Weak locking. */ +#define RCR_WG 0x08 /* Write gathering. */ +#define RCR_WT 0x10 /* Write-through. */ +#define RCR_NLB 0x20 /* LBA# pin is not asserted. */ + +/* AMD Write Allocate Top-Of-Memory and Control Register */ +#define AMD_WT_ALLOC_TME 0x40000 /* top-of-memory enable */ +#define AMD_WT_ALLOC_PRE 0x20000 /* programmable range enable */ +#define AMD_WT_ALLOC_FRE 0x10000 /* fixed (A0000-FFFFF) range enable */ + +/* AMD64 MSR's */ +#define MSR_EFER 0xc0000080 /* extended features */ +#define MSR_K8_UCODE_UPDATE 0xc0010020 /* update microcode */ +#define MSR_MC0_CTL_MASK 0xc0010044 + +/* VIA ACE crypto featureset: for via_feature_rng */ +#define VIA_HAS_RNG 1 /* cpu has RNG */ + +/* VIA ACE crypto featureset: for via_feature_xcrypt */ +#define VIA_HAS_AES 1 /* cpu has AES */ +#define VIA_HAS_SHA 2 /* cpu has SHA1 & SHA256 */ +#define VIA_HAS_MM 4 /* cpu has RSA instructions */ +#define VIA_HAS_AESCTR 8 /* cpu has AES-CTR instructions */ + +/* Centaur Extended Feature flags */ +#define VIA_CPUID_HAS_RNG 0x000004 +#define VIA_CPUID_DO_RNG 0x000008 +#define VIA_CPUID_HAS_ACE 0x000040 +#define VIA_CPUID_DO_ACE 0x000080 +#define VIA_CPUID_HAS_ACE2 0x000100 +#define VIA_CPUID_DO_ACE2 0x000200 +#define VIA_CPUID_HAS_PHE 0x000400 +#define VIA_CPUID_DO_PHE 0x000800 +#define VIA_CPUID_HAS_PMM 0x001000 +#define VIA_CPUID_DO_PMM 0x002000 + +/* VIA ACE xcrypt-* instruction context control options */ +#define VIA_CRYPT_CWLO_ROUND_M 0x0000000f +#define VIA_CRYPT_CWLO_ALG_M 0x00000070 +#define VIA_CRYPT_CWLO_ALG_AES 0x00000000 +#define VIA_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define VIA_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define VIA_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define VIA_CRYPT_CWLO_NORMAL 0x00000000 +#define VIA_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define VIA_CRYPT_CWLO_ENCRYPT 0x00000000 +#define VIA_CRYPT_CWLO_DECRYPT 0x00000200 +#define VIA_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define VIA_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define VIA_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + +#endif /* !_MACHINE_SPECIALREG_HH_ */ |