Index: stable/7/sys/amd64/amd64/amd64_mem.c =================================================================== --- stable/7/sys/amd64/amd64/amd64_mem.c (revision 195685) +++ stable/7/sys/amd64/amd64/amd64_mem.c (revision 195686) @@ -1,686 +1,694 @@ /*- * Copyright (c) 1999 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include /* * amd64 memory range operations * * This code will probably be impenetrable without reference to the * Intel Pentium Pro documentation or x86-64 programmers manual vol 2. */ static char *mem_owner_bios = "BIOS"; #define MR686_FIXMTRR (1<<0) #define mrwithin(mr, a) \ (((a) >= (mr)->mr_base) && ((a) < ((mr)->mr_base + (mr)->mr_len))) #define mroverlap(mra, mrb) \ (mrwithin(mra, mrb->mr_base) || mrwithin(mrb, mra->mr_base)) #define mrvalid(base, len) \ ((!(base & ((1 << 12) - 1))) && /* base is multiple of 4k */ \ ((len) >= (1 << 12)) && /* length is >= 4k */ \ powerof2((len)) && /* ... and power of two */ \ !((base) & ((len) - 1))) /* range is not discontiuous */ #define mrcopyflags(curr, new) \ (((curr) & ~MDF_ATTRMASK) | ((new) & MDF_ATTRMASK)) static int mtrrs_disabled; TUNABLE_INT("machdep.disable_mtrrs", &mtrrs_disabled); SYSCTL_INT(_machdep, OID_AUTO, disable_mtrrs, CTLFLAG_RDTUN, &mtrrs_disabled, 0, "Disable amd64 MTRRs."); static void amd64_mrinit(struct mem_range_softc *sc); static int amd64_mrset(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg); static void amd64_mrAPinit(struct mem_range_softc *sc); static struct mem_range_ops amd64_mrops = { amd64_mrinit, amd64_mrset, amd64_mrAPinit }; /* XXX for AP startup hook */ static u_int64_t mtrrcap, mtrrdef; /* The bitmask for the PhysBase and PhysMask fields of the variable MTRRs. */ static u_int64_t mtrr_physmask; static struct mem_range_desc *mem_range_match(struct mem_range_softc *sc, struct mem_range_desc *mrd); static void amd64_mrfetch(struct mem_range_softc *sc); static int amd64_mtrrtype(int flags); static int amd64_mrt2mtrr(int flags, int oldval); static int amd64_mtrrconflict(int flag1, int flag2); static void amd64_mrstore(struct mem_range_softc *sc); static void amd64_mrstoreone(void *arg); static struct mem_range_desc *amd64_mtrrfixsearch(struct mem_range_softc *sc, u_int64_t addr); static int amd64_mrsetlow(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg); static int amd64_mrsetvariable(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg); /* amd64 MTRR type to memory range type conversion */ static int amd64_mtrrtomrt[] = { MDF_UNCACHEABLE, MDF_WRITECOMBINE, MDF_UNKNOWN, MDF_UNKNOWN, MDF_WRITETHROUGH, MDF_WRITEPROTECT, MDF_WRITEBACK }; #define MTRRTOMRTLEN (sizeof(amd64_mtrrtomrt) / sizeof(amd64_mtrrtomrt[0])) static int amd64_mtrr2mrt(int val) { if (val < 0 || val >= MTRRTOMRTLEN) return (MDF_UNKNOWN); return (amd64_mtrrtomrt[val]); } /* * amd64 MTRR conflicts. Writeback and uncachable may overlap. */ static int amd64_mtrrconflict(int flag1, int flag2) { flag1 &= MDF_ATTRMASK; flag2 &= MDF_ATTRMASK; if ((flag1 & MDF_UNKNOWN) || (flag2 & MDF_UNKNOWN)) return (1); if (flag1 == flag2 || (flag1 == MDF_WRITEBACK && flag2 == MDF_UNCACHEABLE) || (flag2 == MDF_WRITEBACK && flag1 == MDF_UNCACHEABLE)) return (0); return (1); } /* * Look for an exactly-matching range. */ static struct mem_range_desc * mem_range_match(struct mem_range_softc *sc, struct mem_range_desc *mrd) { struct mem_range_desc *cand; int i; for (i = 0, cand = sc->mr_desc; i < sc->mr_ndesc; i++, cand++) if ((cand->mr_base == mrd->mr_base) && (cand->mr_len == mrd->mr_len)) return (cand); return (NULL); } /* * Fetch the current mtrr settings from the current CPU (assumed to * all be in sync in the SMP case). Note that if we are here, we * assume that MTRRs are enabled, and we may or may not have fixed * MTRRs. */ static void amd64_mrfetch(struct mem_range_softc *sc) { struct mem_range_desc *mrd; u_int64_t msrv; int i, j, msr; mrd = sc->mr_desc; /* Get fixed-range MTRRs. */ if (sc->mr_cap & MR686_FIXMTRR) { msr = MSR_MTRR64kBase; for (i = 0; i < (MTRR_N64K / 8); i++, msr++) { msrv = rdmsr(msr); for (j = 0; j < 8; j++, mrd++) { mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | amd64_mtrr2mrt(msrv & 0xff) | MDF_ACTIVE; if (mrd->mr_owner[0] == 0) strcpy(mrd->mr_owner, mem_owner_bios); msrv = msrv >> 8; } } msr = MSR_MTRR16kBase; for (i = 0; i < (MTRR_N16K / 8); i++, msr++) { msrv = rdmsr(msr); for (j = 0; j < 8; j++, mrd++) { mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | amd64_mtrr2mrt(msrv & 0xff) | MDF_ACTIVE; if (mrd->mr_owner[0] == 0) strcpy(mrd->mr_owner, mem_owner_bios); msrv = msrv >> 8; } } msr = MSR_MTRR4kBase; for (i = 0; i < (MTRR_N4K / 8); i++, msr++) { msrv = rdmsr(msr); for (j = 0; j < 8; j++, mrd++) { mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | amd64_mtrr2mrt(msrv & 0xff) | MDF_ACTIVE; if (mrd->mr_owner[0] == 0) strcpy(mrd->mr_owner, mem_owner_bios); msrv = msrv >> 8; } } } /* Get remainder which must be variable MTRRs. */ msr = MSR_MTRRVarBase; for (; (mrd - sc->mr_desc) < sc->mr_ndesc; msr += 2, mrd++) { msrv = rdmsr(msr); mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | amd64_mtrr2mrt(msrv & MTRR_PHYSBASE_TYPE); mrd->mr_base = msrv & mtrr_physmask; msrv = rdmsr(msr + 1); mrd->mr_flags = (msrv & MTRR_PHYSMASK_VALID) ? (mrd->mr_flags | MDF_ACTIVE) : (mrd->mr_flags & ~MDF_ACTIVE); /* Compute the range from the mask. Ick. */ mrd->mr_len = (~(msrv & mtrr_physmask) & (mtrr_physmask | 0xfffL)) + 1; if (!mrvalid(mrd->mr_base, mrd->mr_len)) mrd->mr_flags |= MDF_BOGUS; /* If unclaimed and active, must be the BIOS. */ if ((mrd->mr_flags & MDF_ACTIVE) && (mrd->mr_owner[0] == 0)) strcpy(mrd->mr_owner, mem_owner_bios); } } /* * Return the MTRR memory type matching a region's flags */ static int amd64_mtrrtype(int flags) { int i; flags &= MDF_ATTRMASK; for (i = 0; i < MTRRTOMRTLEN; i++) { if (amd64_mtrrtomrt[i] == MDF_UNKNOWN) continue; if (flags == amd64_mtrrtomrt[i]) return (i); } return (-1); } static int amd64_mrt2mtrr(int flags, int oldval) { int val; if ((val = amd64_mtrrtype(flags)) == -1) return (oldval & 0xff); return (val & 0xff); } /* * Update running CPU(s) MTRRs to match the ranges in the descriptor * list. * * XXX Must be called with interrupts enabled. */ static void amd64_mrstore(struct mem_range_softc *sc) { #ifdef SMP /* * We should use ipi_all_but_self() to call other CPUs into a * locking gate, then call a target function to do this work. * The "proper" solution involves a generalised locking gate * implementation, not ready yet. */ smp_rendezvous(NULL, amd64_mrstoreone, NULL, sc); #else disable_intr(); /* disable interrupts */ amd64_mrstoreone(sc); enable_intr(); #endif } /* * Update the current CPU's MTRRs with those represented in the * descriptor list. Note that we do this wholesale rather than just * stuffing one entry; this is simpler (but slower, of course). */ static void amd64_mrstoreone(void *arg) { struct mem_range_softc *sc = arg; struct mem_range_desc *mrd; u_int64_t omsrv, msrv; int i, j, msr; u_int cr4save; mrd = sc->mr_desc; /* Disable PGE. */ cr4save = rcr4(); if (cr4save & CR4_PGE) load_cr4(cr4save & ~CR4_PGE); /* Disable caches (CD = 1, NW = 0). */ load_cr0((rcr0() & ~CR0_NW) | CR0_CD); /* Flushes caches and TLBs. */ wbinvd(); /* Disable MTRRs (E = 0). */ wrmsr(MSR_MTRRdefType, rdmsr(MSR_MTRRdefType) & ~MTRR_DEF_ENABLE); /* Set fixed-range MTRRs. */ if (sc->mr_cap & MR686_FIXMTRR) { msr = MSR_MTRR64kBase; for (i = 0; i < (MTRR_N64K / 8); i++, msr++) { msrv = 0; omsrv = rdmsr(msr); for (j = 7; j >= 0; j--) { msrv = msrv << 8; msrv |= amd64_mrt2mtrr((mrd + j)->mr_flags, omsrv >> (j * 8)); } wrmsr(msr, msrv); mrd += 8; } msr = MSR_MTRR16kBase; for (i = 0; i < (MTRR_N16K / 8); i++, msr++) { msrv = 0; omsrv = rdmsr(msr); for (j = 7; j >= 0; j--) { msrv = msrv << 8; msrv |= amd64_mrt2mtrr((mrd + j)->mr_flags, omsrv >> (j * 8)); } wrmsr(msr, msrv); mrd += 8; } msr = MSR_MTRR4kBase; for (i = 0; i < (MTRR_N4K / 8); i++, msr++) { msrv = 0; omsrv = rdmsr(msr); for (j = 7; j >= 0; j--) { msrv = msrv << 8; msrv |= amd64_mrt2mtrr((mrd + j)->mr_flags, omsrv >> (j * 8)); } wrmsr(msr, msrv); mrd += 8; } } /* Set remainder which must be variable MTRRs. */ msr = MSR_MTRRVarBase; for (; (mrd - sc->mr_desc) < sc->mr_ndesc; msr += 2, mrd++) { /* base/type register */ omsrv = rdmsr(msr); if (mrd->mr_flags & MDF_ACTIVE) { msrv = mrd->mr_base & mtrr_physmask; msrv |= amd64_mrt2mtrr(mrd->mr_flags, omsrv); } else { msrv = 0; } wrmsr(msr, msrv); /* mask/active register */ if (mrd->mr_flags & MDF_ACTIVE) { msrv = MTRR_PHYSMASK_VALID | (~(mrd->mr_len - 1) & mtrr_physmask); } else { msrv = 0; } wrmsr(msr + 1, msrv); } /* Flush caches, TLBs. */ wbinvd(); /* Enable MTRRs. */ wrmsr(MSR_MTRRdefType, rdmsr(MSR_MTRRdefType) | MTRR_DEF_ENABLE); /* Enable caches (CD = 0, NW = 0). */ load_cr0(rcr0() & ~(CR0_CD | CR0_NW)); /* Restore PGE. */ load_cr4(cr4save); } /* * Hunt for the fixed MTRR referencing (addr) */ static struct mem_range_desc * amd64_mtrrfixsearch(struct mem_range_softc *sc, u_int64_t addr) { struct mem_range_desc *mrd; int i; for (i = 0, mrd = sc->mr_desc; i < (MTRR_N64K + MTRR_N16K + MTRR_N4K); i++, mrd++) if ((addr >= mrd->mr_base) && (addr < (mrd->mr_base + mrd->mr_len))) return (mrd); return (NULL); } /* * Try to satisfy the given range request by manipulating the fixed * MTRRs that cover low memory. * * Note that we try to be generous here; we'll bloat the range out to * the next higher/lower boundary to avoid the consumer having to know * too much about the mechanisms here. * * XXX note that this will have to be updated when we start supporting * "busy" ranges. */ static int amd64_mrsetlow(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) { struct mem_range_desc *first_md, *last_md, *curr_md; /* Range check. */ if (((first_md = amd64_mtrrfixsearch(sc, mrd->mr_base)) == NULL) || ((last_md = amd64_mtrrfixsearch(sc, mrd->mr_base + mrd->mr_len - 1)) == NULL)) return (EINVAL); /* Check that we aren't doing something risky. */ if (!(mrd->mr_flags & MDF_FORCE)) for (curr_md = first_md; curr_md <= last_md; curr_md++) { if ((curr_md->mr_flags & MDF_ATTRMASK) == MDF_UNKNOWN) return (EACCES); } /* Set flags, clear set-by-firmware flag. */ for (curr_md = first_md; curr_md <= last_md; curr_md++) { curr_md->mr_flags = mrcopyflags(curr_md->mr_flags & ~MDF_FIRMWARE, mrd->mr_flags); bcopy(mrd->mr_owner, curr_md->mr_owner, sizeof(mrd->mr_owner)); } return (0); } /* * Modify/add a variable MTRR to satisfy the request. * * XXX needs to be updated to properly support "busy" ranges. */ static int amd64_mrsetvariable(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) { struct mem_range_desc *curr_md, *free_md; int i; /* * Scan the currently active variable descriptors, look for * one we exactly match (straight takeover) and for possible * accidental overlaps. * * Keep track of the first empty variable descriptor in case * we can't perform a takeover. */ i = (sc->mr_cap & MR686_FIXMTRR) ? MTRR_N64K + MTRR_N16K + MTRR_N4K : 0; curr_md = sc->mr_desc + i; free_md = NULL; for (; i < sc->mr_ndesc; i++, curr_md++) { if (curr_md->mr_flags & MDF_ACTIVE) { /* Exact match? */ if ((curr_md->mr_base == mrd->mr_base) && (curr_md->mr_len == mrd->mr_len)) { /* Whoops, owned by someone. */ if (curr_md->mr_flags & MDF_BUSY) return (EBUSY); /* Check that we aren't doing something risky */ if (!(mrd->mr_flags & MDF_FORCE) && ((curr_md->mr_flags & MDF_ATTRMASK) == MDF_UNKNOWN)) return (EACCES); /* Ok, just hijack this entry. */ free_md = curr_md; break; } /* Non-exact overlap? */ if (mroverlap(curr_md, mrd)) { /* Between conflicting region types? */ if (amd64_mtrrconflict(curr_md->mr_flags, mrd->mr_flags)) return (EINVAL); } } else if (free_md == NULL) { free_md = curr_md; } } /* Got somewhere to put it? */ if (free_md == NULL) return (ENOSPC); /* Set up new descriptor. */ free_md->mr_base = mrd->mr_base; free_md->mr_len = mrd->mr_len; free_md->mr_flags = mrcopyflags(MDF_ACTIVE, mrd->mr_flags); bcopy(mrd->mr_owner, free_md->mr_owner, sizeof(mrd->mr_owner)); return (0); } /* * Handle requests to set memory range attributes by manipulating MTRRs. */ static int amd64_mrset(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) { struct mem_range_desc *targ; int error = 0; switch(*arg) { case MEMRANGE_SET_UPDATE: /* * Make sure that what's being asked for is even * possible at all. */ if (!mrvalid(mrd->mr_base, mrd->mr_len) || amd64_mtrrtype(mrd->mr_flags) == -1) return (EINVAL); #define FIXTOP ((MTRR_N64K * 0x10000) + (MTRR_N16K * 0x4000) + (MTRR_N4K * 0x1000)) /* Are the "low memory" conditions applicable? */ if ((sc->mr_cap & MR686_FIXMTRR) && ((mrd->mr_base + mrd->mr_len) <= FIXTOP)) { if ((error = amd64_mrsetlow(sc, mrd, arg)) != 0) return (error); } else { /* It's time to play with variable MTRRs. */ if ((error = amd64_mrsetvariable(sc, mrd, arg)) != 0) return (error); } break; case MEMRANGE_SET_REMOVE: if ((targ = mem_range_match(sc, mrd)) == NULL) return (ENOENT); if (targ->mr_flags & MDF_FIXACTIVE) return (EPERM); if (targ->mr_flags & MDF_BUSY) return (EBUSY); targ->mr_flags &= ~MDF_ACTIVE; targ->mr_owner[0] = 0; break; default: return (EOPNOTSUPP); } /* Update the hardware. */ amd64_mrstore(sc); /* Refetch to see where we're at. */ amd64_mrfetch(sc); return (0); } /* * Work out how many ranges we support, initialise storage for them, * and fetch the initial settings. */ static void amd64_mrinit(struct mem_range_softc *sc) { struct mem_range_desc *mrd; u_int regs[4]; int i, nmdesc = 0, pabits; mtrrcap = rdmsr(MSR_MTRRcap); mtrrdef = rdmsr(MSR_MTRRdefType); /* For now, bail out if MTRRs are not enabled. */ if (!(mtrrdef & MTRR_DEF_ENABLE)) { if (bootverbose) printf("CPU supports MTRRs but not enabled\n"); return; } nmdesc = mtrrcap & MTRR_CAP_VCNT; /* * Determine the size of the PhysMask and PhysBase fields in * the variable range MTRRs. If the extended CPUID 0x80000008 * is present, use that to figure out how many physical * address bits the CPU supports. Otherwise, default to 36 * address bits. */ if (cpu_exthigh >= 0x80000008) { do_cpuid(0x80000008, regs); pabits = regs[0] & 0xff; } else pabits = 36; mtrr_physmask = ((1UL << pabits) - 1) & ~0xfffUL; /* If fixed MTRRs supported and enabled. */ if ((mtrrcap & MTRR_CAP_FIXED) && (mtrrdef & MTRR_DEF_FIXED_ENABLE)) { sc->mr_cap = MR686_FIXMTRR; nmdesc += MTRR_N64K + MTRR_N16K + MTRR_N4K; } sc->mr_desc = malloc(nmdesc * sizeof(struct mem_range_desc), M_MEMDESC, M_WAITOK | M_ZERO); sc->mr_ndesc = nmdesc; mrd = sc->mr_desc; /* Populate the fixed MTRR entries' base/length. */ if (sc->mr_cap & MR686_FIXMTRR) { for (i = 0; i < MTRR_N64K; i++, mrd++) { mrd->mr_base = i * 0x10000; mrd->mr_len = 0x10000; mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE; } for (i = 0; i < MTRR_N16K; i++, mrd++) { mrd->mr_base = i * 0x4000 + 0x80000; mrd->mr_len = 0x4000; mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE; } for (i = 0; i < MTRR_N4K; i++, mrd++) { mrd->mr_base = i * 0x1000 + 0xc0000; mrd->mr_len = 0x1000; mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE; } } /* * Get current settings, anything set now is considered to * have been set by the firmware. (XXX has something already * played here?) */ amd64_mrfetch(sc); mrd = sc->mr_desc; for (i = 0; i < sc->mr_ndesc; i++, mrd++) { if (mrd->mr_flags & MDF_ACTIVE) mrd->mr_flags |= MDF_FIRMWARE; } } /* * Initialise MTRRs on an AP after the BSP has run the init code. */ static void amd64_mrAPinit(struct mem_range_softc *sc) { amd64_mrstoreone(sc); wrmsr(MSR_MTRRdefType, mtrrdef); } static void amd64_mem_drvinit(void *unused) { if (mtrrs_disabled) return; if (!(cpu_feature & CPUID_MTRR)) return; if ((cpu_id & 0xf00) != 0x600 && (cpu_id & 0xf00) != 0xf00) return; - if (cpu_vendor_id != CPU_VENDOR_INTEL && - cpu_vendor_id != CPU_VENDOR_AMD) + switch (cpu_vendor_id) { + case CPU_VENDOR_INTEL: + case CPU_VENDOR_AMD: + break; + case CPU_VENDOR_CENTAUR: + if (cpu_exthigh >= 0x80000008) + break; + /* FALLTHROUGH */ + default: return; + } mem_range_softc.mr_op = &amd64_mrops; } SYSINIT(amd64memdev, SI_SUB_DRIVERS, SI_ORDER_FIRST, amd64_mem_drvinit, NULL); Index: stable/7/sys/amd64/amd64/identcpu.c =================================================================== --- stable/7/sys/amd64/amd64/identcpu.c (revision 195685) +++ stable/7/sys/amd64/amd64/identcpu.c (revision 195686) @@ -1,599 +1,648 @@ /*- * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * Copyright (c) 1997 KATO Takenori. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp */ #include __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* XXX - should be in header file: */ void printcpuinfo(void); void identify_cpu(void); void earlysetcpuclass(void); void panicifcpuunsupported(void); static u_int find_cpu_vendor_id(void); static void print_AMD_info(void); static void print_AMD_assoc(int i); +static void print_via_padlock_info(void); int cpu_class; char machine[] = "amd64"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class"); static char cpu_model[128]; SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model"); static int hw_clockrate; SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, &hw_clockrate, 0, "CPU instruction clock rate"); static char cpu_brand[48]; static struct { char *cpu_name; int cpu_class; } amd64_cpus[] = { { "Clawhammer", CPUCLASS_K8 }, /* CPU_CLAWHAMMER */ { "Sledgehammer", CPUCLASS_K8 }, /* CPU_SLEDGEHAMMER */ }; static struct { char *vendor; u_int vendor_id; } cpu_vendors[] = { { INTEL_VENDOR_ID, CPU_VENDOR_INTEL }, /* GenuineIntel */ { AMD_VENDOR_ID, CPU_VENDOR_AMD }, /* AuthenticAMD */ { CENTAUR_VENDOR_ID, CPU_VENDOR_CENTAUR }, /* CentaurHauls */ }; void printcpuinfo(void) { u_int regs[4], i; char *brand; cpu_class = amd64_cpus[cpu].cpu_class; printf("CPU: "); strncpy(cpu_model, amd64_cpus[cpu].cpu_name, sizeof (cpu_model)); /* Check for extended CPUID information and a processor name. */ if (cpu_exthigh >= 0x80000004) { brand = cpu_brand; for (i = 0x80000002; i < 0x80000005; i++) { do_cpuid(i, regs); memcpy(brand, regs, sizeof(regs)); brand += sizeof(regs); } } - if (cpu_vendor_id == CPU_VENDOR_INTEL) { + switch (cpu_vendor_id) { + case CPU_VENDOR_INTEL: /* Please make up your mind folks! */ strcat(cpu_model, "EM64T"); - } else if (cpu_vendor_id == CPU_VENDOR_AMD) { + break; + case CPU_VENDOR_AMD: /* * Values taken from AMD Processor Recognition * http://www.amd.com/K6/k6docs/pdf/20734g.pdf * (also describes ``Features'' encodings. */ strcpy(cpu_model, "AMD "); - switch (cpu_id & 0xF00) { - case 0xf00: + if ((cpu_id & 0xf00) == 0xf00) strcat(cpu_model, "AMD64 Processor"); - break; - default: + else strcat(cpu_model, "Unknown"); - break; - } + break; + case CPU_VENDOR_CENTAUR: + strcpy(cpu_model, "VIA "); + if ((cpu_id & 0xff0) == 0x6f0) + strcat(cpu_model, "Nano Processor"); + else + strcat(cpu_model, "Unknown"); + break; + default: + strcat(cpu_model, "Unknown"); + break; } /* * Replace cpu_model with cpu_brand minus leading spaces if * we have one. */ brand = cpu_brand; while (*brand == ' ') ++brand; if (*brand != '\0') strcpy(cpu_model, brand); printf("%s (", cpu_model); switch(cpu_class) { case CPUCLASS_K8: hw_clockrate = (tsc_freq + 5000) / 1000000; printf("%jd.%02d-MHz ", (intmax_t)(tsc_freq + 4999) / 1000000, (u_int)((tsc_freq + 4999) / 10000) % 100); printf("K8"); break; default: printf("Unknown"); /* will panic below... */ } printf("-class CPU)\n"); if (*cpu_vendor) printf(" Origin = \"%s\"", cpu_vendor); if (cpu_id) printf(" Id = 0x%x", cpu_id); if (cpu_vendor_id == CPU_VENDOR_INTEL || - cpu_vendor_id == CPU_VENDOR_AMD) { + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_CENTAUR) { printf(" Stepping = %u", cpu_id & 0xf); if (cpu_high > 0) { u_int cmp = 1, htt = 1; /* * Here we should probably set up flags indicating * whether or not various features are available. * The interesting ones are probably VME, PSE, PAE, * and PGE. The code already assumes without bothering * to check that all CPUs >= Pentium have a TSC and * MSRs. */ printf("\n Features=0x%b", cpu_feature, "\020" "\001FPU" /* Integral FPU */ "\002VME" /* Extended VM86 mode support */ "\003DE" /* Debugging Extensions (CR4.DE) */ "\004PSE" /* 4MByte page tables */ "\005TSC" /* Timestamp counter */ "\006MSR" /* Machine specific registers */ "\007PAE" /* Physical address extension */ "\010MCE" /* Machine Check support */ "\011CX8" /* CMPEXCH8 instruction */ "\012APIC" /* SMP local APIC */ "\013oldMTRR" /* Previous implementation of MTRR */ "\014SEP" /* Fast System Call */ "\015MTRR" /* Memory Type Range Registers */ "\016PGE" /* PG_G (global bit) support */ "\017MCA" /* Machine Check Architecture */ "\020CMOV" /* CMOV instruction */ "\021PAT" /* Page attributes table */ "\022PSE36" /* 36 bit address space support */ "\023PN" /* Processor Serial number */ "\024CLFLUSH" /* Has the CLFLUSH instruction */ "\025" "\026DTS" /* Debug Trace Store */ "\027ACPI" /* ACPI support */ "\030MMX" /* MMX instructions */ "\031FXSR" /* FXSAVE/FXRSTOR */ "\032SSE" /* Streaming SIMD Extensions */ "\033SSE2" /* Streaming SIMD Extensions #2 */ "\034SS" /* Self snoop */ "\035HTT" /* Hyperthreading (see EBX bit 16-23) */ "\036TM" /* Thermal Monitor clock slowdown */ "\037IA64" /* CPU can execute IA64 instructions */ "\040PBE" /* Pending Break Enable */ ); if (cpu_feature2 != 0) { printf("\n Features2=0x%b", cpu_feature2, "\020" "\001SSE3" /* SSE3 */ "\002" "\003DTES64" /* 64-bit Debug Trace */ "\004MON" /* MONITOR/MWAIT Instructions */ "\005DS_CPL" /* CPL Qualified Debug Store */ "\006VMX" /* Virtual Machine Extensions */ "\007SMX" /* Safer Mode Extensions */ "\010EST" /* Enhanced SpeedStep */ "\011TM2" /* Thermal Monitor 2 */ "\012SSSE3" /* SSSE3 */ "\013CNXT-ID" /* L1 context ID available */ "\014" "\015" "\016CX16" /* CMPXCHG16B Instruction */ "\017xTPR" /* Send Task Priority Messages*/ "\020PDCM" /* Perf/Debug Capability MSR */ "\021" "\022" "\023DCA" /* Direct Cache Access */ "\024SSE4.1" "\025SSE4.2" "\026x2APIC" /* xAPIC Extensions */ "\027" "\030POPCNT" "\031" "\032" "\033XSAVE" "\034OSXSAVE" "\035" "\036" "\037" "\040" ); } /* * AMD64 Architecture Programmer's Manual Volume 3: * General-Purpose and System Instructions * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf * * IA-32 Intel Architecture Software Developer's Manual, * Volume 2A: Instruction Set Reference, A-M * ftp://download.intel.com/design/Pentium4/manuals/25366617.pdf */ if (amd_feature != 0) { printf("\n AMD Features=0x%b", amd_feature, "\020" /* in hex */ "\001" /* Same */ "\002" /* Same */ "\003" /* Same */ "\004" /* Same */ "\005" /* Same */ "\006" /* Same */ "\007" /* Same */ "\010" /* Same */ "\011" /* Same */ "\012" /* Same */ "\013" /* Undefined */ "\014SYSCALL" /* Have SYSCALL/SYSRET */ "\015" /* Same */ "\016" /* Same */ "\017" /* Same */ "\020" /* Same */ "\021" /* Same */ "\022" /* Same */ "\023" /* Reserved, unknown */ "\024MP" /* Multiprocessor Capable */ "\025NX" /* Has EFER.NXE, NX */ "\026" /* Undefined */ "\027MMX+" /* AMD MMX Extensions */ "\030" /* Same */ "\031" /* Same */ "\032FFXSR" /* Fast FXSAVE/FXRSTOR */ "\033Page1GB" /* 1-GB large page support */ "\034RDTSCP" /* RDTSCP */ "\035" /* Undefined */ "\036LM" /* 64 bit long mode */ "\0373DNow!+" /* AMD 3DNow! Extensions */ "\0403DNow!" /* AMD 3DNow! */ ); } if (amd_feature2 != 0) { printf("\n AMD Features2=0x%b", amd_feature2, "\020" "\001LAHF" /* LAHF/SAHF in long mode */ "\002CMP" /* CMP legacy */ "\003SVM" /* Secure Virtual Mode */ "\004ExtAPIC" /* Extended APIC register */ "\005CR8" /* CR8 in legacy mode */ "\006ABM" /* LZCNT instruction */ "\007SSE4A" /* SSE4A */ "\010MAS" /* Misaligned SSE mode */ "\011Prefetch" /* 3DNow! Prefetch/PrefetchW */ "\012OSVW" /* OS visible workaround */ "\013IBS" /* Instruction based sampling */ "\014SSE5" /* SSE5 */ "\015SKINIT" /* SKINIT/STGI */ "\016WDT" /* Watchdog timer */ "\017" "\020" "\021" "\022" "\023" "\024" "\025" "\026" "\027" "\030" "\031" "\032" "\033" "\034" "\035" "\036" "\037" "\040" ); } + if (cpu_vendor_id == CPU_VENDOR_CENTAUR) + print_via_padlock_info(); + if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_AMD) cpu_feature &= ~CPUID_HTT; /* * If this CPU supports P-state invariant TSC then * mention the capability. */ switch (cpu_vendor_id) { case CPU_VENDOR_AMD: if ((amd_pminfo & AMDPM_TSC_INVARIANT) || AMD64_CPU_FAMILY(cpu_id) >= 0x10 || cpu_id == 0x60fb2) tsc_is_invariant = 1; break; case CPU_VENDOR_INTEL: if ((amd_pminfo & AMDPM_TSC_INVARIANT) || (AMD64_CPU_FAMILY(cpu_id) == 0x6 && AMD64_CPU_MODEL(cpu_id) >= 0xe) || (AMD64_CPU_FAMILY(cpu_id) == 0xf && AMD64_CPU_MODEL(cpu_id) >= 0x3)) tsc_is_invariant = 1; break; case CPU_VENDOR_CENTAUR: if (AMD64_CPU_FAMILY(cpu_id) == 0x6 && AMD64_CPU_MODEL(cpu_id) >= 0xf && (rdmsr(0x1203) & 0x100000000ULL) == 0) tsc_is_invariant = 1; break; } if (tsc_is_invariant) printf("\n TSC: P-state invariant"); /* * If this CPU supports HTT or CMP then mention the * number of physical/logical cores it contains. */ if (cpu_feature & CPUID_HTT) htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16; if (cpu_vendor_id == CPU_VENDOR_AMD && (amd_feature2 & AMDID2_CMP)) cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1; else if (cpu_vendor_id == CPU_VENDOR_INTEL && (cpu_high >= 4)) { cpuid_count(4, 0, regs); if ((regs[0] & 0x1f) != 0) cmp = ((regs[0] >> 26) & 0x3f) + 1; } if (cmp > 1) printf("\n Cores per package: %d", cmp); if ((htt / cmp) > 1) printf("\n Logical CPUs per core: %d", htt / cmp); } } /* Avoid ugly blank lines: only print newline when we have to. */ if (*cpu_vendor || cpu_id) printf("\n"); if (!bootverbose) return; if (cpu_vendor_id == CPU_VENDOR_AMD) print_AMD_info(); } void panicifcpuunsupported(void) { #ifndef HAMMER #error "You need to specify a cpu type" #endif /* * Now that we have told the user what they have, * let them know if that machine type isn't configured. */ switch (cpu_class) { case CPUCLASS_X86: #ifndef HAMMER case CPUCLASS_K8: #endif panic("CPU class not configured"); default: break; } } /* Update TSC freq with the value indicated by the caller. */ static void tsc_freq_changed(void *arg, const struct cf_level *level, int status) { /* * If there was an error during the transition or * TSC is P-state invariant, don't do anything. */ if (status != 0 || tsc_is_invariant) return; /* Total setting for this level gives the new frequency in MHz. */ hw_clockrate = level->total_set.freq; } EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL, EVENTHANDLER_PRI_ANY); /* - * Final stage of CPU identification. -- Should I check TI? + * Final stage of CPU identification. */ void identify_cpu(void) { u_int regs[4]; do_cpuid(0, regs); cpu_high = regs[0]; ((u_int *)&cpu_vendor)[0] = regs[1]; ((u_int *)&cpu_vendor)[1] = regs[3]; ((u_int *)&cpu_vendor)[2] = regs[2]; cpu_vendor[12] = '\0'; cpu_vendor_id = find_cpu_vendor_id(); do_cpuid(1, regs); cpu_id = regs[0]; cpu_procinfo = regs[1]; cpu_feature = regs[3]; cpu_feature2 = regs[2]; if (cpu_vendor_id == CPU_VENDOR_INTEL || - cpu_vendor_id == CPU_VENDOR_AMD) { + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_CENTAUR) { do_cpuid(0x80000000, regs); cpu_exthigh = regs[0]; } if (cpu_exthigh >= 0x80000001) { do_cpuid(0x80000001, regs); amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff); amd_feature2 = regs[2]; } if (cpu_exthigh >= 0x80000007) { do_cpuid(0x80000007, regs); amd_pminfo = regs[3]; } if (cpu_exthigh >= 0x80000008) { do_cpuid(0x80000008, regs); cpu_procinfo2 = regs[2]; } /* XXX */ cpu = CPU_CLAWHAMMER; } static u_int find_cpu_vendor_id(void) { int i; for (i = 0; i < sizeof(cpu_vendors) / sizeof(cpu_vendors[0]); i++) if (strcmp(cpu_vendor, cpu_vendors[i].vendor) == 0) return (cpu_vendors[i].vendor_id); return (0); } static void print_AMD_assoc(int i) { if (i == 255) printf(", fully associative\n"); else printf(", %d-way associative\n", i); } static void print_AMD_l2_assoc(int i) { switch (i & 0x0f) { case 0: printf(", disabled/not present\n"); break; case 1: printf(", direct mapped\n"); break; case 2: printf(", 2-way associative\n"); break; case 4: printf(", 4-way associative\n"); break; case 6: printf(", 8-way associative\n"); break; case 8: printf(", 16-way associative\n"); break; case 15: printf(", fully associative\n"); break; default: printf(", reserved configuration\n"); break; } } static void print_AMD_info(void) { u_int regs[4]; if (cpu_exthigh < 0x80000005) return; do_cpuid(0x80000005, regs); printf("L1 2MB data TLB: %d entries", (regs[0] >> 16) & 0xff); print_AMD_assoc(regs[0] >> 24); printf("L1 2MB instruction TLB: %d entries", regs[0] & 0xff); print_AMD_assoc((regs[0] >> 8) & 0xff); printf("L1 4KB data TLB: %d entries", (regs[1] >> 16) & 0xff); print_AMD_assoc(regs[1] >> 24); printf("L1 4KB instruction TLB: %d entries", regs[1] & 0xff); print_AMD_assoc((regs[1] >> 8) & 0xff); printf("L1 data cache: %d kbytes", regs[2] >> 24); printf(", %d bytes/line", regs[2] & 0xff); printf(", %d lines/tag", (regs[2] >> 8) & 0xff); print_AMD_assoc((regs[2] >> 16) & 0xff); printf("L1 instruction cache: %d kbytes", regs[3] >> 24); printf(", %d bytes/line", regs[3] & 0xff); printf(", %d lines/tag", (regs[3] >> 8) & 0xff); print_AMD_assoc((regs[3] >> 16) & 0xff); if (cpu_exthigh >= 0x80000006) { do_cpuid(0x80000006, regs); if ((regs[0] >> 16) != 0) { printf("L2 2MB data TLB: %d entries", (regs[0] >> 16) & 0xfff); print_AMD_l2_assoc(regs[0] >> 28); printf("L2 2MB instruction TLB: %d entries", regs[0] & 0xfff); print_AMD_l2_assoc((regs[0] >> 28) & 0xf); } else { printf("L2 2MB unified TLB: %d entries", regs[0] & 0xfff); print_AMD_l2_assoc((regs[0] >> 28) & 0xf); } if ((regs[1] >> 16) != 0) { printf("L2 4KB data TLB: %d entries", (regs[1] >> 16) & 0xfff); print_AMD_l2_assoc(regs[1] >> 28); printf("L2 4KB instruction TLB: %d entries", (regs[1] >> 16) & 0xfff); print_AMD_l2_assoc((regs[1] >> 28) & 0xf); } else { printf("L2 4KB unified TLB: %d entries", (regs[1] >> 16) & 0xfff); print_AMD_l2_assoc((regs[1] >> 28) & 0xf); } printf("L2 unified cache: %d kbytes", regs[2] >> 16); printf(", %d bytes/line", regs[2] & 0xff); printf(", %d lines/tag", (regs[2] >> 8) & 0x0f); print_AMD_l2_assoc((regs[2] >> 12) & 0x0f); } +} + +static void +print_via_padlock_info(void) +{ + u_int regs[4]; + + /* Check for supported models. */ + switch (cpu_id & 0xff0) { + case 0x690: + if ((cpu_id & 0xf) < 3) + return; + case 0x6a0: + case 0x6d0: + case 0x6f0: + break; + default: + return; + } + + do_cpuid(0xc0000000, regs); + if (regs[0] >= 0xc0000001) + do_cpuid(0xc0000001, regs); + else + return; + + printf("\n VIA Padlock Features=0x%b", regs[3], + "\020" + "\003RNG" /* RNG */ + "\007AES" /* ACE */ + "\011AES-CTR" /* ACE2 */ + "\013SHA1,SHA256" /* PHE */ + "\015RSA" /* PMM */ + ); } Index: stable/7/sys/amd64/amd64/initcpu.c =================================================================== --- stable/7/sys/amd64/amd64/initcpu.c (revision 195685) +++ stable/7/sys/amd64/amd64/initcpu.c (revision 195686) @@ -1,84 +1,159 @@ /*- * Copyright (c) KATO Takenori, 1997, 1998. * * All rights reserved. Unpublished rights reserved under the copyright * laws of Japan. * * 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 as * the first lines of this file unmodified. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_cpu.h" #include #include #include #include #include #include #include #include #include static int hw_instruction_sse; SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); int cpu; /* Are we 386, 386sx, 486, etc? */ u_int cpu_feature; /* Feature flags */ u_int cpu_feature2; /* Feature flags */ u_int amd_feature; /* AMD feature flags */ u_int amd_feature2; /* AMD feature flags */ u_int amd_pminfo; /* AMD advanced power management info */ +u_int via_feature_rng; /* VIA RNG features */ +u_int via_feature_xcrypt; /* VIA ACE features */ u_int cpu_high; /* Highest arg to CPUID */ u_int cpu_exthigh; /* Highest arg to extended CPUID */ u_int cpu_id; /* Stepping ID */ u_int cpu_procinfo; /* HyperThreading Info / Brand Index / CLFUSH */ u_int cpu_procinfo2; /* Multicore info */ char cpu_vendor[20]; /* CPU Origin code */ u_int cpu_vendor_id; /* CPU vendor ID */ u_int cpu_fxsr; /* SSE enabled */ u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */ +SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD, + &via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU"); +SYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD, + &via_feature_xcrypt, 0, "VIA C3/C7 xcrypt feature available in CPU"); + /* + * Initialize special VIA C3/C7 features + */ +static void +init_via(void) +{ + u_int regs[4], val; + u_int64_t msreg; + + do_cpuid(0xc0000000, regs); + val = regs[0]; + if (val >= 0xc0000001) { + do_cpuid(0xc0000001, regs); + val = regs[3]; + } else + val = 0; + + /* Enable RNG if present and disabled */ + if (val & VIA_CPUID_HAS_RNG) { + if (!(val & VIA_CPUID_DO_RNG)) { + msreg = rdmsr(0x110B); + msreg |= 0x40; + wrmsr(0x110B, msreg); + } + via_feature_rng = VIA_HAS_RNG; + } + /* Enable AES engine if present and disabled */ + if (val & VIA_CPUID_HAS_ACE) { + if (!(val & VIA_CPUID_DO_ACE)) { + msreg = rdmsr(0x1107); + msreg |= (0x01 << 28); + wrmsr(0x1107, msreg); + } + via_feature_xcrypt |= VIA_HAS_AES; + } + /* Enable ACE2 engine if present and disabled */ + if (val & VIA_CPUID_HAS_ACE2) { + if (!(val & VIA_CPUID_DO_ACE2)) { + msreg = rdmsr(0x1107); + msreg |= (0x01 << 28); + wrmsr(0x1107, msreg); + } + via_feature_xcrypt |= VIA_HAS_AESCTR; + } + /* Enable SHA engine if present and disabled */ + if (val & VIA_CPUID_HAS_PHE) { + if (!(val & VIA_CPUID_DO_PHE)) { + msreg = rdmsr(0x1107); + msreg |= (0x01 << 28/**/); + wrmsr(0x1107, msreg); + } + via_feature_xcrypt |= VIA_HAS_SHA; + } + /* Enable MM engine if present and disabled */ + if (val & VIA_CPUID_HAS_PMM) { + if (!(val & VIA_CPUID_DO_PMM)) { + msreg = rdmsr(0x1107); + msreg |= (0x01 << 28/**/); + wrmsr(0x1107, msreg); + } + via_feature_xcrypt |= VIA_HAS_MM; + } +} + +/* * Initialize CPU control registers */ void initializecpu(void) { uint64_t msr; if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) { load_cr4(rcr4() | CR4_FXSR | CR4_XMM); cpu_fxsr = hw_instruction_sse = 1; } if ((amd_feature & AMDID_NX) != 0) { msr = rdmsr(MSR_EFER) | EFER_NXE; wrmsr(MSR_EFER, msr); pg_nx = PG_NX; } + if (cpu_vendor_id == CPU_VENDOR_CENTAUR && + AMD64_CPU_FAMILY(cpu_id) == 0x6 && + AMD64_CPU_MODEL(cpu_id) >= 0xf) + init_via(); } Index: stable/7/sys/amd64/amd64/msi.c =================================================================== --- stable/7/sys/amd64/amd64/msi.c (revision 195685) +++ stable/7/sys/amd64/amd64/msi.c (revision 195686) @@ -1,507 +1,517 @@ /*- * Copyright (c) 2006 Yahoo!, Inc. * All rights reserved. * Written by: John Baldwin * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY 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. */ /* * Support for PCI Message Signalled Interrupts (MSI). MSI interrupts on * x86 are basically APIC messages that the northbridge delivers directly * to the local APICs as if they had come from an I/O APIC. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include /* Fields in address for Intel MSI messages. */ #define MSI_INTEL_ADDR_DEST 0x000ff000 #define MSI_INTEL_ADDR_RH 0x00000008 # define MSI_INTEL_ADDR_RH_ON 0x00000008 # define MSI_INTEL_ADDR_RH_OFF 0x00000000 #define MSI_INTEL_ADDR_DM 0x00000004 # define MSI_INTEL_ADDR_DM_PHYSICAL 0x00000000 # define MSI_INTEL_ADDR_DM_LOGICAL 0x00000004 /* Fields in data for Intel MSI messages. */ #define MSI_INTEL_DATA_TRGRMOD IOART_TRGRMOD /* Trigger mode. */ # define MSI_INTEL_DATA_TRGREDG IOART_TRGREDG # define MSI_INTEL_DATA_TRGRLVL IOART_TRGRLVL #define MSI_INTEL_DATA_LEVEL 0x00004000 /* Polarity. */ # define MSI_INTEL_DATA_DEASSERT 0x00000000 # define MSI_INTEL_DATA_ASSERT 0x00004000 #define MSI_INTEL_DATA_DELMOD IOART_DELMOD /* Delivery mode. */ # define MSI_INTEL_DATA_DELFIXED IOART_DELFIXED # define MSI_INTEL_DATA_DELLOPRI IOART_DELLOPRI # define MSI_INTEL_DATA_DELSMI IOART_DELSMI # define MSI_INTEL_DATA_DELNMI IOART_DELNMI # define MSI_INTEL_DATA_DELINIT IOART_DELINIT # define MSI_INTEL_DATA_DELEXINT IOART_DELEXINT #define MSI_INTEL_DATA_INTVEC IOART_INTVEC /* Interrupt vector. */ /* * Build Intel MSI message and data values from a source. AMD64 systems * seem to be compatible, so we use the same function for both. */ #define INTEL_ADDR(msi) \ (MSI_INTEL_ADDR_BASE | (msi)->msi_cpu << 12 | \ MSI_INTEL_ADDR_RH_OFF | MSI_INTEL_ADDR_DM_PHYSICAL) #define INTEL_DATA(msi) \ (MSI_INTEL_DATA_TRGREDG | MSI_INTEL_DATA_DELFIXED | (msi)->msi_vector) static MALLOC_DEFINE(M_MSI, "msi", "PCI MSI"); /* * MSI sources are bunched into groups. This is because MSI forces * all of the messages to share the address and data registers and * thus certain properties (such as the local APIC ID target on x86). * Each group has a 'first' source that contains information global to * the group. These fields are marked with (g) below. * * Note that local APIC ID is kind of special. Each message will be * assigned an ID by the system; however, a group will use the ID from * the first message. * * For MSI-X, each message is isolated. */ struct msi_intsrc { struct intsrc msi_intsrc; device_t msi_dev; /* Owning device. (g) */ struct msi_intsrc *msi_first; /* First source in group. */ u_int msi_irq; /* IRQ cookie. */ u_int msi_msix; /* MSI-X message. */ u_int msi_vector:8; /* IDT vector. */ u_int msi_cpu:8; /* Local APIC ID. (g) */ u_int msi_count:8; /* Messages in this group. (g) */ }; static void msi_create_source(void); static void msi_enable_source(struct intsrc *isrc); static void msi_disable_source(struct intsrc *isrc, int eoi); static void msi_eoi_source(struct intsrc *isrc); static void msi_enable_intr(struct intsrc *isrc); static void msi_disable_intr(struct intsrc *isrc); static int msi_vector(struct intsrc *isrc); static int msi_source_pending(struct intsrc *isrc); static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig, enum intr_polarity pol); static void msi_assign_cpu(struct intsrc *isrc, u_int apic_id); struct pic msi_pic = { msi_enable_source, msi_disable_source, msi_eoi_source, msi_enable_intr, msi_disable_intr, msi_vector, msi_source_pending, NULL, NULL, msi_config_intr, msi_assign_cpu }; static int msi_enabled; static int msi_last_irq; static struct mtx msi_lock; static void msi_enable_source(struct intsrc *isrc) { } static void msi_disable_source(struct intsrc *isrc, int eoi) { if (eoi == PIC_EOI) lapic_eoi(); } static void msi_eoi_source(struct intsrc *isrc) { lapic_eoi(); } static void msi_enable_intr(struct intsrc *isrc) { struct msi_intsrc *msi = (struct msi_intsrc *)isrc; apic_enable_vector(msi->msi_vector); } static void msi_disable_intr(struct intsrc *isrc) { struct msi_intsrc *msi = (struct msi_intsrc *)isrc; apic_disable_vector(msi->msi_vector); } static int msi_vector(struct intsrc *isrc) { struct msi_intsrc *msi = (struct msi_intsrc *)isrc; return (msi->msi_irq); } static int msi_source_pending(struct intsrc *isrc) { return (0); } static int msi_config_intr(struct intsrc *isrc, enum intr_trigger trig, enum intr_polarity pol) { return (ENODEV); } static void msi_assign_cpu(struct intsrc *isrc, u_int apic_id) { struct msi_intsrc *msi = (struct msi_intsrc *)isrc; msi->msi_cpu = apic_id; if (bootverbose) printf("msi: Assigning %s IRQ %d to local APIC %u\n", msi->msi_msix ? "MSI-X" : "MSI", msi->msi_irq, msi->msi_cpu); pci_remap_msi_irq(msi->msi_dev, msi->msi_irq); } void msi_init(void) { /* Check if we have a supported CPU. */ - if (!(cpu_vendor_id == CPU_VENDOR_INTEL || - cpu_vendor_id == CPU_VENDOR_AMD)) + switch (cpu_vendor_id) { + case CPU_VENDOR_INTEL: + case CPU_VENDOR_AMD: + break; + case CPU_VENDOR_CENTAUR: + if (AMD64_CPU_FAMILY(cpu_id) == 0x6 && + AMD64_CPU_MODEL(cpu_id) >= 0xf) + break; + /* FALLTHROUGH */ + default: return; + } msi_enabled = 1; intr_register_pic(&msi_pic); mtx_init(&msi_lock, "msi", NULL, MTX_DEF); } void msi_create_source(void) { struct msi_intsrc *msi; u_int irq; mtx_lock(&msi_lock); if (msi_last_irq >= NUM_MSI_INTS) { mtx_unlock(&msi_lock); return; } irq = msi_last_irq + FIRST_MSI_INT; msi_last_irq++; mtx_unlock(&msi_lock); msi = malloc(sizeof(struct msi_intsrc), M_MSI, M_WAITOK | M_ZERO); msi->msi_intsrc.is_pic = &msi_pic; msi->msi_irq = irq; intr_register_source(&msi->msi_intsrc); nexus_add_irq(irq); } /* * Try to allocate 'count' interrupt sources with contiguous IDT values. If * we allocate any new sources, then their IRQ values will be at the end of * the irqs[] array, with *newirq being the index of the first new IRQ value * and *newcount being the number of new IRQ values added. */ int msi_alloc(device_t dev, int count, int maxcount, int *irqs) { struct msi_intsrc *msi, *fsrc; int cnt, i, vector; if (!msi_enabled) return (ENXIO); again: mtx_lock(&msi_lock); /* Try to find 'count' free IRQs. */ cnt = 0; for (i = FIRST_MSI_INT; i < FIRST_MSI_INT + NUM_MSI_INTS; i++) { msi = (struct msi_intsrc *)intr_lookup_source(i); /* End of allocated sources, so break. */ if (msi == NULL) break; /* If this is a free one, save its IRQ in the array. */ if (msi->msi_dev == NULL) { irqs[cnt] = i; cnt++; if (cnt == count) break; } } /* Do we need to create some new sources? */ if (cnt < count) { /* If we would exceed the max, give up. */ if (i + (count - cnt) > FIRST_MSI_INT + NUM_MSI_INTS) { mtx_unlock(&msi_lock); return (ENXIO); } mtx_unlock(&msi_lock); /* We need count - cnt more sources. */ while (cnt < count) { msi_create_source(); cnt++; } goto again; } /* Ok, we now have the IRQs allocated. */ KASSERT(cnt == count, ("count mismatch")); /* Allocate 'count' IDT vectors. */ vector = apic_alloc_vectors(irqs, count, maxcount); if (vector == 0) { mtx_unlock(&msi_lock); return (ENOSPC); } /* Assign IDT vectors and make these messages owned by 'dev'. */ fsrc = (struct msi_intsrc *)intr_lookup_source(irqs[0]); for (i = 0; i < count; i++) { msi = (struct msi_intsrc *)intr_lookup_source(irqs[i]); msi->msi_dev = dev; msi->msi_vector = vector + i; if (bootverbose) printf("msi: routing MSI IRQ %d to vector %u\n", msi->msi_irq, msi->msi_vector); msi->msi_first = fsrc; KASSERT(msi->msi_intsrc.is_handlers == 0, ("dead MSI has handlers")); } fsrc->msi_count = count; mtx_unlock(&msi_lock); return (0); } int msi_release(int *irqs, int count) { struct msi_intsrc *msi, *first; int i; mtx_lock(&msi_lock); first = (struct msi_intsrc *)intr_lookup_source(irqs[0]); if (first == NULL) { mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this isn't an MSI-X message. */ if (first->msi_msix) { mtx_unlock(&msi_lock); return (EINVAL); } /* Make sure this message is allocated to a group. */ if (first->msi_first == NULL) { mtx_unlock(&msi_lock); return (ENXIO); } /* * Make sure this is the start of a group and that we are releasing * the entire group. */ if (first->msi_first != first || first->msi_count != count) { mtx_unlock(&msi_lock); return (EINVAL); } KASSERT(first->msi_dev != NULL, ("unowned group")); /* Clear all the extra messages in the group. */ for (i = 1; i < count; i++) { msi = (struct msi_intsrc *)intr_lookup_source(irqs[i]); KASSERT(msi->msi_first == first, ("message not in group")); KASSERT(msi->msi_dev == first->msi_dev, ("owner mismatch")); msi->msi_first = NULL; msi->msi_dev = NULL; apic_free_vector(msi->msi_vector, msi->msi_irq); msi->msi_vector = 0; } /* Clear out the first message. */ first->msi_first = NULL; first->msi_dev = NULL; apic_free_vector(first->msi_vector, first->msi_irq); first->msi_vector = 0; first->msi_count = 0; mtx_unlock(&msi_lock); return (0); } int msi_map(int irq, uint64_t *addr, uint32_t *data) { struct msi_intsrc *msi; mtx_lock(&msi_lock); msi = (struct msi_intsrc *)intr_lookup_source(irq); if (msi == NULL) { mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this message is allocated to a device. */ if (msi->msi_dev == NULL) { mtx_unlock(&msi_lock); return (ENXIO); } /* * If this message isn't an MSI-X message, make sure it's part * of a group, and switch to the first message in the * group. */ if (!msi->msi_msix) { if (msi->msi_first == NULL) { mtx_unlock(&msi_lock); return (ENXIO); } msi = msi->msi_first; } *addr = INTEL_ADDR(msi); *data = INTEL_DATA(msi); mtx_unlock(&msi_lock); return (0); } int msix_alloc(device_t dev, int *irq) { struct msi_intsrc *msi; int i, vector; if (!msi_enabled) return (ENXIO); again: mtx_lock(&msi_lock); /* Find a free IRQ. */ for (i = FIRST_MSI_INT; i < FIRST_MSI_INT + NUM_MSI_INTS; i++) { msi = (struct msi_intsrc *)intr_lookup_source(i); /* End of allocated sources, so break. */ if (msi == NULL) break; /* Stop at the first free source. */ if (msi->msi_dev == NULL) break; } /* Do we need to create a new source? */ if (msi == NULL) { /* If we would exceed the max, give up. */ if (i + 1 > FIRST_MSI_INT + NUM_MSI_INTS) { mtx_unlock(&msi_lock); return (ENXIO); } mtx_unlock(&msi_lock); /* Create a new source. */ msi_create_source(); goto again; } /* Allocate an IDT vector. */ vector = apic_alloc_vector(i); if (bootverbose) printf("msi: routing MSI-X IRQ %d to vector %u\n", msi->msi_irq, vector); /* Setup source. */ msi->msi_dev = dev; msi->msi_vector = vector; msi->msi_msix = 1; KASSERT(msi->msi_intsrc.is_handlers == 0, ("dead MSI-X has handlers")); mtx_unlock(&msi_lock); *irq = i; return (0); } int msix_release(int irq) { struct msi_intsrc *msi; mtx_lock(&msi_lock); msi = (struct msi_intsrc *)intr_lookup_source(irq); if (msi == NULL) { mtx_unlock(&msi_lock); return (ENOENT); } /* Make sure this is an MSI-X message. */ if (!msi->msi_msix) { mtx_unlock(&msi_lock); return (EINVAL); } KASSERT(msi->msi_dev != NULL, ("unowned message")); /* Clear out the message. */ msi->msi_dev = NULL; apic_free_vector(msi->msi_vector, msi->msi_irq); msi->msi_vector = 0; msi->msi_msix = 0; mtx_unlock(&msi_lock); return (0); } Index: stable/7/sys/amd64/include/md_var.h =================================================================== --- stable/7/sys/amd64/include/md_var.h (revision 195685) +++ stable/7/sys/amd64/include/md_var.h (revision 195686) @@ -1,86 +1,88 @@ /*- * 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_H_ #define _MACHINE_MD_VAR_H_ /* * Miscellaneous machine-dependent declarations. */ extern long Maxmem; extern u_int basemem; 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_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 char kstack[]; extern char sigcode[]; extern int szsigcode; extern uint64_t *vm_page_dump; extern int vm_page_dump_size; 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 busdma_swi(void); void cpu_setregs(void); void doreti_iret(void) __asm(__STRING(doreti_iret)); void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault)); void dump_add_page(vm_paddr_t); void dump_drop_page(vm_paddr_t); void initializecpu(void); void fillw(int /*u_short*/ pat, void *base, size_t cnt); void fpstate_drop(struct thread *td); int is_physical_memory(vm_paddr_t addr); int isa_nmi(int cd); void pagecopy(void *from, void *to); void pagezero(void *addr); void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist); int user_dbreg_trap(void); void minidumpsys(struct dumperinfo *); #endif /* !_MACHINE_MD_VAR_H_ */ Index: stable/7/sys/amd64/include/specialreg.h =================================================================== --- stable/7/sys/amd64/include/specialreg.h (revision 195685) +++ stable/7/sys/amd64/include/specialreg.h (revision 195686) @@ -1,462 +1,498 @@ /*- * 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_H_ #define _MACHINE_SPECIALREG_H_ /* * 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_SCE 0x000000001 /* System Call Extensions (R/W) */ #define EFER_LME 0x000000100 /* Long mode enable (R/W) */ #define EFER_LMA 0x000000400 /* Long mode active (R) */ #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_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_DCA 0x00040000 #define CPUID2_SSE41 0x00080000 #define CPUID2_SSE42 0x00100000 #define CPUID2_X2APIC 0x00200000 #define CPUID2_POPCNT 0x00800000 /* * 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 AMD64_CPU_MODEL(id) \ ((((id) & CPUID_MODEL) >> 4) | \ (((id) & CPUID_EXT_MODEL) >> 12)) #define AMD64_CPU_FAMILY(id) \ ((((id) & CPUID_FAMILY) >> 8) + \ (((id) & CPUID_EXT_FAMILY) >> 20)) /* * 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 /* * 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 INTEL_VENDOR_ID "GenuineIntel" /* * 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_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_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)(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 0x0000000000000400UL #define MTRR_CAP_FIXED 0x0000000000000100UL #define MTRR_CAP_VCNT 0x00000000000000ffUL #define MTRR_DEF_ENABLE 0x0000000000000800UL #define MTRR_DEF_FIXED_ENABLE 0x0000000000000400UL #define MTRR_DEF_TYPE 0x00000000000000ffUL #define MTRR_PHYSBASE_PHYSBASE 0x000ffffffffff000UL #define MTRR_PHYSBASE_TYPE 0x00000000000000ffUL #define MTRR_PHYSMASK_PHYSMASK 0x000ffffffffff000UL #define MTRR_PHYSMASK_VALID 0x0000000000000800UL /* 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 /* * 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_STAR 0xc0000081 /* legacy mode SYSCALL target/cs/ss */ #define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target rip */ #define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target rip */ #define MSR_SF_MASK 0xc0000084 /* syscall flags mask */ #define MSR_FSBASE 0xc0000100 /* base address of the %fs "segment" */ #define MSR_GSBASE 0xc0000101 /* base address of the %gs "segment" */ #define MSR_KGSBASE 0xc0000102 /* base address of the kernel %gs */ #define MSR_PERFEVSEL0 0xc0010000 #define MSR_PERFEVSEL1 0xc0010001 #define MSR_PERFEVSEL2 0xc0010002 #define MSR_PERFEVSEL3 0xc0010003 #undef MSR_PERFCTR0 #undef MSR_PERFCTR1 #define MSR_PERFCTR0 0xc0010004 #define MSR_PERFCTR1 0xc0010005 #define MSR_PERFCTR2 0xc0010006 #define MSR_PERFCTR3 0xc0010007 #define MSR_SYSCFG 0xc0010010 #define MSR_IORRBASE0 0xc0010016 #define MSR_IORRMASK0 0xc0010017 #define MSR_IORRBASE1 0xc0010018 #define MSR_IORRMASK1 0xc0010019 #define MSR_TOP_MEM 0xc001001a /* boundary for ram below 4G */ #define MSR_TOP_MEM2 0xc001001d /* boundary for ram above 4G */ #define MSR_K8_UCODE_UPDATE 0xc0010020 /* update microcode */ +/* 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_H_ */ Index: stable/7/sys/conf/files.amd64 =================================================================== --- stable/7/sys/conf/files.amd64 (revision 195685) +++ stable/7/sys/conf/files.amd64 (revision 195686) @@ -1,270 +1,273 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # # linux32_genassym.o optional compat_linux32 \ dependency "$S/amd64/linux32/linux32_genassym.c" \ compile-with "${CC} ${CFLAGS:N-fno-common} -c ${.IMPSRC}" \ no-obj no-implicit-rule \ clean "linux32_genassym.o" # linux32_assym.h optional compat_linux32 \ dependency "$S/kern/genassym.sh linux32_genassym.o" \ compile-with "sh $S/kern/genassym.sh linux32_genassym.o > ${.TARGET}" \ no-obj no-implicit-rule before-depend \ clean "linux32_assym.h" # ia32_genassym.o standard \ dependency "$S/compat/ia32/ia32_genassym.c" \ compile-with "${CC} ${CFLAGS:N-fno-common} -c ${.IMPSRC}" \ no-obj no-implicit-rule \ clean "ia32_genassym.o" # ia32_assym.h standard \ dependency "$S/kern/genassym.sh ia32_genassym.o" \ compile-with "env NM='${NM}' sh $S/kern/genassym.sh ia32_genassym.o > ${.TARGET}" \ no-obj no-implicit-rule before-depend \ clean "ia32_assym.h" # font.h optional sc_dflt_font \ compile-with "uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'static u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'static u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'static u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h" \ no-obj no-implicit-rule before-depend \ clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8" # atkbdmap.h optional atkbd_dflt_keymap \ compile-with "/usr/sbin/kbdcontrol -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \ no-obj no-implicit-rule before-depend \ clean "atkbdmap.h" # ukbdmap.h optional ukbd_dflt_keymap \ compile-with "/usr/sbin/kbdcontrol -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \ no-obj no-implicit-rule before-depend \ clean "ukbdmap.h" # nvenetlib.o optional nve pci \ dependency "$S/contrib/dev/nve/amd64/nvenetlib.o.bz2.uu" \ compile-with "uudecode $S/contrib/dev/nve/amd64/nvenetlib.o.bz2.uu ; bzip2 -df nvenetlib.o.bz2" \ no-implicit-rule # os+%DIKED-nve.h optional nve pci \ dependency "$S/contrib/dev/nve/os.h" \ compile-with "sed -e 's/^.*#include.*phy\.h.*$$//' $S/contrib/dev/nve/os.h > os+%DIKED-nve.h" \ no-implicit-rule no-obj before-depend \ clean "os+%DIKED-nve.h" # hptmvraid.o optional hptmv \ dependency "$S/dev/hptmv/amd64-elf.raid.o.uu" \ compile-with "uudecode < $S/dev/hptmv/amd64-elf.raid.o.uu" \ no-implicit-rule # hptrr_lib.o optional hptrr \ dependency "$S/dev/hptrr/amd64-elf.hptrr_lib.o.uu" \ compile-with "uudecode < $S/dev/hptrr/amd64-elf.hptrr_lib.o.uu" \ no-implicit-rule # # amd64/acpica/OsdEnvironment.c optional acpi amd64/acpica/acpi_machdep.c optional acpi amd64/acpica/acpi_wakeup.c optional acpi amd64/acpica/madt.c optional acpi amd64/amd64/amd64_mem.c optional mem #amd64/amd64/apic_vector.S standard amd64/amd64/atomic.c standard amd64/amd64/autoconf.c standard amd64/amd64/bios.c standard amd64/amd64/bpf_jit_machdep.c optional bpf_jitter amd64/amd64/busdma_machdep.c standard amd64/amd64/cpu_switch.S standard amd64/amd64/db_disasm.c optional ddb amd64/amd64/db_interface.c optional ddb amd64/amd64/db_trace.c optional ddb amd64/amd64/dump_machdep.c standard amd64/amd64/elf_machdep.c standard amd64/amd64/exception.S standard amd64/amd64/fpu.c standard amd64/amd64/gdb_machdep.c optional gdb amd64/amd64/identcpu.c standard amd64/amd64/in_cksum.c optional inet amd64/amd64/initcpu.c standard amd64/amd64/intr_machdep.c standard amd64/amd64/io.c optional io amd64/amd64/io_apic.c standard amd64/amd64/legacy.c standard amd64/amd64/local_apic.c standard amd64/amd64/locore.S standard no-obj amd64/amd64/machdep.c standard amd64/amd64/mem.c optional mem amd64/amd64/minidump_machdep.c standard amd64/amd64/mp_machdep.c optional smp amd64/amd64/mp_watchdog.c optional mp_watchdog smp amd64/amd64/mpboot.S optional smp amd64/amd64/mptable.c optional mptable amd64/amd64/mptable_pci.c optional mptable pci amd64/amd64/msi.c optional pci amd64/amd64/nexus.c standard amd64/amd64/pmap.c standard amd64/amd64/prof_machdep.c optional profiling-routine amd64/amd64/sigtramp.S standard amd64/amd64/stack_machdep.c optional ddb | stack amd64/amd64/support.S standard amd64/amd64/sys_machdep.c standard amd64/amd64/trap.c standard amd64/amd64/tsc.c standard amd64/amd64/uio_machdep.c standard amd64/amd64/uma_machdep.c standard amd64/amd64/vm_machdep.c standard amd64/isa/atpic.c optional atpic isa #amd64/isa/atpic_vector.S optional atpic isa amd64/isa/clock.c standard amd64/isa/elcr.c standard amd64/isa/isa.c standard amd64/isa/isa_dma.c standard amd64/isa/nmi.c standard amd64/pci/pci_bus.c optional pci amd64/pci/pci_cfgreg.c optional pci crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb +crypto/via/padlock.c optional padlock +crypto/via/padlock_cipher.c optional padlock +crypto/via/padlock_hash.c optional padlock dev/acpica/acpi_if.m standard dev/amdtemp/amdtemp.c optional amdtemp dev/arcmsr/arcmsr.c optional arcmsr pci dev/atkbdc/atkbd.c optional atkbd atkbdc dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc dev/atkbdc/atkbdc.c optional atkbdc dev/atkbdc/atkbdc_isa.c optional atkbdc isa dev/atkbdc/atkbdc_subr.c optional atkbdc dev/atkbdc/psm.c optional psm atkbdc dev/coretemp/coretemp.c optional coretemp dev/cpuctl/cpuctl.c optional cpuctl # There are no systems with isa slots, so all ed isa entries should go.. dev/ed/if_ed_3c503.c optional ed isa ed_3c503 dev/ed/if_ed_isa.c optional ed isa dev/ed/if_ed_wd80x3.c optional ed isa dev/ed/if_ed_hpp.c optional ed isa ed_hpp dev/ed/if_ed_sic.c optional ed isa ed_sic dev/fb/fb.c optional fb | vga dev/fb/vga.c optional vga dev/ichwd/ichwd.c optional ichwd dev/if_ndis/if_ndis.c optional ndis dev/if_ndis/if_ndis_pccard.c optional ndis pccard dev/if_ndis/if_ndis_pci.c optional ndis cardbus | ndis pci dev/if_ndis/if_ndis_usb.c optional ndis usb dev/io/iodev.c optional io dev/ipmi/ipmi.c optional ipmi dev/ipmi/ipmi_acpi.c optional ipmi acpi dev/ipmi/ipmi_isa.c optional ipmi isa dev/ipmi/ipmi_kcs.c optional ipmi dev/ipmi/ipmi_smic.c optional ipmi dev/ipmi/ipmi_smbus.c optional ipmi smbus dev/ipmi/ipmi_smbios.c optional ipmi dev/ipmi/ipmi_ssif.c optional ipmi smbus dev/ipmi/ipmi_pci.c optional ipmi pci dev/fdc/fdc.c optional fdc dev/fdc/fdc_acpi.c optional fdc dev/fdc/fdc_isa.c optional fdc isa dev/fdc/fdc_pccard.c optional fdc pccard dev/hptmv/entry.c optional hptmv dev/hptmv/mv.c optional hptmv dev/hptmv/gui_lib.c optional hptmv dev/hptmv/hptproc.c optional hptmv dev/hptmv/ioctl.c optional hptmv dev/hptrr/hptrr_os_bsd.c optional hptrr dev/hptrr/hptrr_osm_bsd.c optional hptrr dev/hptrr/hptrr_config.c optional hptrr dev/hwpmc/hwpmc_amd.c optional hwpmc dev/hwpmc/hwpmc_intel.c optional hwpmc dev/hwpmc/hwpmc_core.c optional hwpmc dev/hwpmc/hwpmc_piv.c optional hwpmc dev/hwpmc/hwpmc_tsc.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc dev/kbd/kbd.c optional atkbd | sc | ukbd dev/mem/memutil.c optional mem dev/nfe/if_nfe.c optional nfe pci dev/nve/if_nve.c optional nve pci dev/nvram/nvram.c optional nvram isa dev/sio/sio.c optional sio dev/sio/sio_isa.c optional sio isa dev/sio/sio_pccard.c optional sio pccard dev/sio/sio_pci.c optional sio pci dev/sio/sio_puc.c optional sio puc dev/speaker/spkr.c optional speaker dev/syscons/apm/apm_saver.c optional apm_saver apm dev/syscons/scterm-sc.c optional sc dev/syscons/scvgarndr.c optional sc vga dev/syscons/scvtb.c optional sc dev/uart/uart_cpu_amd64.c optional uart dev/wpi/if_wpi.c optional wpi isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/link_elf_obj.c standard pci/agp_amd64.c optional agp pci/agp_i810.c optional agp pci/agp_intel.c optional agp pci/agp_via.c optional agp # # IA32 binary support # #amd64/ia32/ia32_exception.S optional compat_ia32 amd64/ia32/ia32_reg.c optional compat_ia32 amd64/ia32/ia32_signal.c optional compat_ia32 amd64/ia32/ia32_sigtramp.S optional compat_ia32 amd64/ia32/ia32_syscall.c optional compat_ia32 compat/freebsd32/freebsd32_ioctl.c optional compat_ia32 compat/freebsd32/freebsd32_misc.c optional compat_ia32 compat/freebsd32/freebsd32_syscalls.c optional compat_ia32 compat/freebsd32/freebsd32_sysent.c optional compat_ia32 compat/ia32/ia32_sysvec.c optional compat_ia32 compat/linprocfs/linprocfs.c optional linprocfs compat/linsysfs/linsysfs.c optional linsysfs kern/imgact_elf32.c optional compat_ia32 # # Linux/i386 binary support # amd64/linux32/linux32_dummy.c optional compat_linux32 amd64/linux32/linux32_locore.s optional compat_linux32 \ dependency "linux32_assym.h" amd64/linux32/linux32_machdep.c optional compat_linux32 amd64/linux32/linux32_support.s optional compat_linux32 \ dependency "linux32_assym.h" amd64/linux32/linux32_sysent.c optional compat_linux32 amd64/linux32/linux32_sysvec.c optional compat_linux32 compat/linux/linux_emul.c optional compat_linux32 compat/linux/linux_file.c optional compat_linux32 compat/linux/linux_futex.c optional compat_linux32 compat/linux/linux_getcwd.c optional compat_linux32 compat/linux/linux_ioctl.c optional compat_linux32 compat/linux/linux_ipc.c optional compat_linux32 compat/linux/linux_mib.c optional compat_linux32 compat/linux/linux_misc.c optional compat_linux32 compat/linux/linux_signal.c optional compat_linux32 compat/linux/linux_socket.c optional compat_linux32 compat/linux/linux_stats.c optional compat_linux32 compat/linux/linux_sysctl.c optional compat_linux32 compat/linux/linux_time.c optional compat_linux32 compat/linux/linux_uid16.c optional compat_linux32 compat/linux/linux_util.c optional compat_linux32 dev/amr/amr_linux.c optional compat_linux32 amr dev/mfi/mfi_linux.c optional compat_linux32 mfi # # Windows NDIS driver support # compat/ndis/kern_ndis.c optional ndisapi pci compat/ndis/kern_windrv.c optional ndisapi pci compat/ndis/subr_hal.c optional ndisapi pci compat/ndis/subr_ndis.c optional ndisapi pci compat/ndis/subr_ntoskrnl.c optional ndisapi pci compat/ndis/subr_pe.c optional ndisapi pci compat/ndis/subr_usbd.c optional ndisapi pci compat/ndis/winx64_wrap.S optional ndisapi pci i386/bios/smbios.c optional smbios i386/bios/vpd.c optional vpd i386/cpufreq/powernow.c optional cpufreq i386/cpufreq/est.c optional cpufreq i386/cpufreq/p4tcc.c optional cpufreq # libkern/memset.c standard Index: stable/7/sys/contrib/pf =================================================================== --- stable/7/sys/contrib/pf (revision 195685) +++ stable/7/sys/contrib/pf (revision 195686) Property changes on: stable/7/sys/contrib/pf ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys/contrib/pf:r187109,187112 Index: stable/7/sys/crypto/via/padlock.c =================================================================== --- stable/7/sys/crypto/via/padlock.c (revision 195685) +++ stable/7/sys/crypto/via/padlock.c (revision 195686) @@ -1,394 +1,394 @@ /*- * Copyright (c) 2005-2006 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include -#if defined(__i386__) && !defined(PC98) +#if defined(__amd64__) || (defined(__i386__) && !defined(PC98)) #include #include #include #include #endif #include #include #include #include #include "cryptodev_if.h" /* * Technical documentation about the PadLock engine can be found here: * * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/programming_guide.pdf */ struct padlock_softc { int32_t sc_cid; uint32_t sc_sid; TAILQ_HEAD(, padlock_session) sc_sessions; struct mtx sc_sessions_mtx; }; static int padlock_newsession(device_t, uint32_t *sidp, struct cryptoini *cri); static int padlock_freesession(device_t, uint64_t tid); static int padlock_process(device_t, struct cryptop *crp, int hint __unused); MALLOC_DEFINE(M_PADLOCK, "padlock_data", "PadLock Data"); static void padlock_identify(device_t *dev, device_t parent) { /* NB: order 10 is so we get attached after h/w devices */ if (device_find_child(parent, "padlock", -1) == NULL && BUS_ADD_CHILD(parent, 10, "padlock", -1) == 0) panic("padlock: could not attach"); } static int padlock_probe(device_t dev) { char capp[256]; -#if defined(__i386__) && !defined(PC98) +#if defined(__amd64__) || (defined(__i386__) && !defined(PC98)) /* If there is no AES support, we has nothing to do here. */ if (!(via_feature_xcrypt & VIA_HAS_AES)) { device_printf(dev, "No ACE support.\n"); return (EINVAL); } strlcpy(capp, "AES-CBC", sizeof(capp)); #if 0 strlcat(capp, ",AES-EBC", sizeof(capp)); strlcat(capp, ",AES-CFB", sizeof(capp)); strlcat(capp, ",AES-OFB", sizeof(capp)); #endif if (via_feature_xcrypt & VIA_HAS_SHA) { strlcat(capp, ",SHA1", sizeof(capp)); strlcat(capp, ",SHA256", sizeof(capp)); } #if 0 if (via_feature_xcrypt & VIA_HAS_AESCTR) strlcat(capp, ",AES-CTR", sizeof(capp)); if (via_feature_xcrypt & VIA_HAS_MM) strlcat(capp, ",RSA", sizeof(capp)); #endif device_set_desc_copy(dev, capp); return (0); #else return (EINVAL); #endif } static int padlock_attach(device_t dev) { struct padlock_softc *sc = device_get_softc(dev); TAILQ_INIT(&sc->sc_sessions); sc->sc_sid = 1; sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE); if (sc->sc_cid < 0) { device_printf(dev, "Could not get crypto driver id.\n"); return (ENOMEM); } mtx_init(&sc->sc_sessions_mtx, "padlock_mtx", NULL, MTX_DEF); crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0); crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); crypto_register(sc->sc_cid, CRYPTO_RIPEMD160_HMAC, 0, 0); crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0); crypto_register(sc->sc_cid, CRYPTO_SHA2_384_HMAC, 0, 0); crypto_register(sc->sc_cid, CRYPTO_SHA2_512_HMAC, 0, 0); return (0); } static int padlock_detach(device_t dev) { struct padlock_softc *sc = device_get_softc(dev); struct padlock_session *ses; mtx_lock(&sc->sc_sessions_mtx); TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) { if (ses->ses_used) { mtx_unlock(&sc->sc_sessions_mtx); device_printf(dev, "Cannot detach, sessions still active.\n"); return (EBUSY); } } for (ses = TAILQ_FIRST(&sc->sc_sessions); ses != NULL; ses = TAILQ_FIRST(&sc->sc_sessions)) { TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next); free(ses, M_PADLOCK); } mtx_destroy(&sc->sc_sessions_mtx); crypto_unregister_all(sc->sc_cid); return (0); } static int padlock_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri) { struct padlock_softc *sc = device_get_softc(dev); struct padlock_session *ses = NULL; struct cryptoini *encini, *macini; int error; if (sidp == NULL || cri == NULL) return (EINVAL); encini = macini = NULL; for (; cri != NULL; cri = cri->cri_next) { switch (cri->cri_alg) { case CRYPTO_NULL_HMAC: case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: case CRYPTO_RIPEMD160_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: if (macini != NULL) return (EINVAL); macini = cri; break; case CRYPTO_AES_CBC: if (encini != NULL) return (EINVAL); encini = cri; break; default: return (EINVAL); } } /* * We only support HMAC algorithms to be able to work with * ipsec(4), so if we are asked only for authentication without * encryption, don't pretend we can accellerate it. */ if (encini == NULL) return (EINVAL); /* * Let's look for a free session structure. */ mtx_lock(&sc->sc_sessions_mtx); /* * Free sessions goes first, so if first session is used, we need to * allocate one. */ ses = TAILQ_FIRST(&sc->sc_sessions); if (ses == NULL || ses->ses_used) ses = NULL; else { TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next); ses->ses_used = 1; TAILQ_INSERT_TAIL(&sc->sc_sessions, ses, ses_next); } mtx_unlock(&sc->sc_sessions_mtx); if (ses == NULL) { ses = malloc(sizeof(*ses), M_PADLOCK, M_NOWAIT | M_ZERO); if (ses == NULL) return (ENOMEM); ses->ses_used = 1; mtx_lock(&sc->sc_sessions_mtx); ses->ses_id = sc->sc_sid++; TAILQ_INSERT_TAIL(&sc->sc_sessions, ses, ses_next); mtx_unlock(&sc->sc_sessions_mtx); } error = padlock_cipher_setup(ses, encini); if (error != 0) { padlock_freesession(NULL, ses->ses_id); return (error); } if (macini != NULL) { error = padlock_hash_setup(ses, macini); if (error != 0) { padlock_freesession(NULL, ses->ses_id); return (error); } } *sidp = ses->ses_id; return (0); } static int padlock_freesession(device_t dev, uint64_t tid) { struct padlock_softc *sc = device_get_softc(dev); struct padlock_session *ses; uint32_t sid = ((uint32_t)tid) & 0xffffffff; mtx_lock(&sc->sc_sessions_mtx); TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) { if (ses->ses_id == sid) break; } if (ses == NULL) { mtx_unlock(&sc->sc_sessions_mtx); return (EINVAL); } TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next); padlock_hash_free(ses); bzero(ses, sizeof(*ses)); ses->ses_used = 0; TAILQ_INSERT_TAIL(&sc->sc_sessions, ses, ses_next); mtx_unlock(&sc->sc_sessions_mtx); return (0); } static int padlock_process(device_t dev, struct cryptop *crp, int hint __unused) { struct padlock_softc *sc = device_get_softc(dev); struct padlock_session *ses = NULL; struct cryptodesc *crd, *enccrd, *maccrd; int error = 0; enccrd = maccrd = NULL; if (crp == NULL || crp->crp_callback == NULL || crp->crp_desc == NULL) { error = EINVAL; goto out; } for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) { switch (crd->crd_alg) { case CRYPTO_NULL_HMAC: case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: case CRYPTO_RIPEMD160_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: if (maccrd != NULL) { error = EINVAL; goto out; } maccrd = crd; break; case CRYPTO_AES_CBC: if (enccrd != NULL) { error = EINVAL; goto out; } enccrd = crd; break; default: return (EINVAL); } } if (enccrd == NULL || (enccrd->crd_len % AES_BLOCK_LEN) != 0) { error = EINVAL; goto out; } mtx_lock(&sc->sc_sessions_mtx); TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) { if (ses->ses_id == (crp->crp_sid & 0xffffffff)) break; } mtx_unlock(&sc->sc_sessions_mtx); if (ses == NULL) { error = EINVAL; goto out; } /* Perform data authentication if requested before encryption. */ if (maccrd != NULL && maccrd->crd_next == enccrd) { error = padlock_hash_process(ses, maccrd, crp); if (error != 0) goto out; } error = padlock_cipher_process(ses, enccrd, crp); if (error != 0) goto out; /* Perform data authentication if requested after encryption. */ if (maccrd != NULL && enccrd->crd_next == maccrd) { error = padlock_hash_process(ses, maccrd, crp); if (error != 0) goto out; } out: #if 0 /* * This code is not necessary, because contexts will be freed on next * padlock_setup_mackey() call or at padlock_freesession() call. */ if (ses != NULL && maccrd != NULL && (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) { padlock_free_ctx(ses->ses_axf, ses->ses_ictx); padlock_free_ctx(ses->ses_axf, ses->ses_octx); } #endif crp->crp_etype = error; crypto_done(crp); return (error); } static device_method_t padlock_methods[] = { DEVMETHOD(device_identify, padlock_identify), DEVMETHOD(device_probe, padlock_probe), DEVMETHOD(device_attach, padlock_attach), DEVMETHOD(device_detach, padlock_detach), DEVMETHOD(cryptodev_newsession, padlock_newsession), DEVMETHOD(cryptodev_freesession,padlock_freesession), DEVMETHOD(cryptodev_process, padlock_process), {0, 0}, }; static driver_t padlock_driver = { "padlock", padlock_methods, sizeof(struct padlock_softc), }; static devclass_t padlock_devclass; /* XXX where to attach */ DRIVER_MODULE(padlock, nexus, padlock_driver, padlock_devclass, 0, 0); MODULE_VERSION(padlock, 1); MODULE_DEPEND(padlock, crypto, 1, 1, 1); Index: stable/7/sys/crypto/via/padlock_hash.c =================================================================== --- stable/7/sys/crypto/via/padlock_hash.c (revision 195685) +++ stable/7/sys/crypto/via/padlock_hash.c (revision 195686) @@ -1,391 +1,391 @@ /*- * Copyright (c) 2006 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include -#if defined(__i386__) && !defined(PC98) +#if defined(__amd64__) || (defined(__i386__) && !defined(PC98)) #include #include #include #include #endif #include #include /* for hmac_ipad_buffer and hmac_opad_buffer */ #include #include /* * Implementation notes. * * Some VIA CPUs provides SHA1 and SHA256 acceleration. * We implement all HMAC algorithms provided by crypto(9) framework, but we do * the crypto work in software unless this is HMAC/SHA1 or HMAC/SHA256 and * our CPU can accelerate it. * * Additional CPU instructions, which preform SHA1 and SHA256 are one-shot * functions - we have only one chance to give the data, CPU itself will add * the padding and calculate hash automatically. * This means, it is not possible to implement common init(), update(), final() * methods. * The way I've choosen is to keep adding data to the buffer on update() * (reallocating the buffer if necessary) and call XSHA{1,256} instruction on * final(). */ struct padlock_sha_ctx { uint8_t *psc_buf; int psc_offset; int psc_size; }; CTASSERT(sizeof(struct padlock_sha_ctx) <= sizeof(union authctx)); static void padlock_sha_init(struct padlock_sha_ctx *ctx); static int padlock_sha_update(struct padlock_sha_ctx *ctx, uint8_t *buf, uint16_t bufsize); static void padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx); static void padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx); static struct auth_hash padlock_hmac_sha1 = { CRYPTO_SHA1_HMAC, "HMAC-SHA1", 20, SHA1_HASH_LEN, SHA1_HMAC_BLOCK_LEN, sizeof(struct padlock_sha_ctx), (void (*)(void *))padlock_sha_init, (int (*)(void *, uint8_t *, uint16_t))padlock_sha_update, (void (*)(uint8_t *, void *))padlock_sha1_final }; static struct auth_hash padlock_hmac_sha256 = { CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256", 32, SHA2_256_HASH_LEN, SHA2_256_HMAC_BLOCK_LEN, sizeof(struct padlock_sha_ctx), (void (*)(void *))padlock_sha_init, (int (*)(void *, uint8_t *, uint16_t))padlock_sha_update, (void (*)(uint8_t *, void *))padlock_sha256_final }; MALLOC_DECLARE(M_PADLOCK); static __inline void padlock_output_block(uint32_t *src, uint32_t *dst, size_t count) { while (count-- > 0) *dst++ = bswap32(*src++); } static void padlock_do_sha1(const u_char *in, u_char *out, int count) { u_char buf[128+16]; /* PadLock needs at least 128 bytes buffer. */ u_char *result = PADLOCK_ALIGN(buf); ((uint32_t *)result)[0] = 0x67452301; ((uint32_t *)result)[1] = 0xEFCDAB89; ((uint32_t *)result)[2] = 0x98BADCFE; ((uint32_t *)result)[3] = 0x10325476; ((uint32_t *)result)[4] = 0xC3D2E1F0; #ifdef __GNUCLIKE_ASM __asm __volatile( ".byte 0xf3, 0x0f, 0xa6, 0xc8" /* rep xsha1 */ : "+S"(in), "+D"(result) : "c"(count), "a"(0) ); #endif padlock_output_block((uint32_t *)result, (uint32_t *)out, SHA1_HASH_LEN / sizeof(uint32_t)); } static void padlock_do_sha256(const char *in, char *out, int count) { char buf[128+16]; /* PadLock needs at least 128 bytes buffer. */ char *result = PADLOCK_ALIGN(buf); ((uint32_t *)result)[0] = 0x6A09E667; ((uint32_t *)result)[1] = 0xBB67AE85; ((uint32_t *)result)[2] = 0x3C6EF372; ((uint32_t *)result)[3] = 0xA54FF53A; ((uint32_t *)result)[4] = 0x510E527F; ((uint32_t *)result)[5] = 0x9B05688C; ((uint32_t *)result)[6] = 0x1F83D9AB; ((uint32_t *)result)[7] = 0x5BE0CD19; #ifdef __GNUCLIKE_ASM __asm __volatile( ".byte 0xf3, 0x0f, 0xa6, 0xd0" /* rep xsha256 */ : "+S"(in), "+D"(result) : "c"(count), "a"(0) ); #endif padlock_output_block((uint32_t *)result, (uint32_t *)out, SHA2_256_HASH_LEN / sizeof(uint32_t)); } static void padlock_sha_init(struct padlock_sha_ctx *ctx) { ctx->psc_buf = NULL; ctx->psc_offset = 0; ctx->psc_size = 0; } static int padlock_sha_update(struct padlock_sha_ctx *ctx, uint8_t *buf, uint16_t bufsize) { if (ctx->psc_size - ctx->psc_offset < bufsize) { ctx->psc_size = MAX(ctx->psc_size * 2, ctx->psc_size + bufsize); ctx->psc_buf = realloc(ctx->psc_buf, ctx->psc_size, M_PADLOCK, M_NOWAIT); if(ctx->psc_buf == NULL) return (ENOMEM); } bcopy(buf, ctx->psc_buf + ctx->psc_offset, bufsize); ctx->psc_offset += bufsize; return (0); } static void padlock_sha_free(struct padlock_sha_ctx *ctx) { if (ctx->psc_buf != NULL) { //bzero(ctx->psc_buf, ctx->psc_size); free(ctx->psc_buf, M_PADLOCK); ctx->psc_buf = NULL; ctx->psc_offset = 0; ctx->psc_size = 0; } } static void padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx) { padlock_do_sha1(ctx->psc_buf, hash, ctx->psc_offset); padlock_sha_free(ctx); } static void padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx) { padlock_do_sha256(ctx->psc_buf, hash, ctx->psc_offset); padlock_sha_free(ctx); } static void padlock_copy_ctx(struct auth_hash *axf, void *sctx, void *dctx) { if ((via_feature_xcrypt & VIA_HAS_SHA) != 0 && (axf->type == CRYPTO_SHA1_HMAC || axf->type == CRYPTO_SHA2_256_HMAC)) { struct padlock_sha_ctx *spctx = sctx, *dpctx = dctx; dpctx->psc_offset = spctx->psc_offset; dpctx->psc_size = spctx->psc_size; dpctx->psc_buf = malloc(dpctx->psc_size, M_PADLOCK, M_WAITOK); bcopy(spctx->psc_buf, dpctx->psc_buf, dpctx->psc_size); } else { bcopy(sctx, dctx, axf->ctxsize); } } static void padlock_free_ctx(struct auth_hash *axf, void *ctx) { if ((via_feature_xcrypt & VIA_HAS_SHA) != 0 && (axf->type == CRYPTO_SHA1_HMAC || axf->type == CRYPTO_SHA2_256_HMAC)) { padlock_sha_free(ctx); } } static void padlock_hash_key_setup(struct padlock_session *ses, caddr_t key, int klen) { struct auth_hash *axf; int i; klen /= 8; axf = ses->ses_axf; /* * Try to free contexts before using them, because * padlock_hash_key_setup() can be called twice - once from * padlock_newsession() and again from padlock_process(). */ padlock_free_ctx(axf, ses->ses_ictx); padlock_free_ctx(axf, ses->ses_octx); for (i = 0; i < klen; i++) key[i] ^= HMAC_IPAD_VAL; axf->Init(ses->ses_ictx); axf->Update(ses->ses_ictx, key, klen); axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen); for (i = 0; i < klen; i++) key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); axf->Init(ses->ses_octx); axf->Update(ses->ses_octx, key, klen); axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen); for (i = 0; i < klen; i++) key[i] ^= HMAC_OPAD_VAL; } /* * Compute keyed-hash authenticator. */ static int padlock_authcompute(struct padlock_session *ses, struct cryptodesc *crd, caddr_t buf, int flags) { u_char hash[HASH_MAX_LEN]; struct auth_hash *axf; union authctx ctx; int error; axf = ses->ses_axf; padlock_copy_ctx(axf, ses->ses_ictx, &ctx); error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); if (error != 0) { padlock_free_ctx(axf, &ctx); return (error); } axf->Final(hash, &ctx); padlock_copy_ctx(axf, ses->ses_octx, &ctx); axf->Update(&ctx, hash, axf->hashsize); axf->Final(hash, &ctx); /* Inject the authentication data */ crypto_copyback(flags, buf, crd->crd_inject, ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash); return (0); } int padlock_hash_setup(struct padlock_session *ses, struct cryptoini *macini) { ses->ses_mlen = macini->cri_mlen; /* Find software structure which describes HMAC algorithm. */ switch (macini->cri_alg) { case CRYPTO_NULL_HMAC: ses->ses_axf = &auth_hash_null; break; case CRYPTO_MD5_HMAC: ses->ses_axf = &auth_hash_hmac_md5; break; case CRYPTO_SHA1_HMAC: if ((via_feature_xcrypt & VIA_HAS_SHA) != 0) ses->ses_axf = &padlock_hmac_sha1; else ses->ses_axf = &auth_hash_hmac_sha1; break; case CRYPTO_RIPEMD160_HMAC: ses->ses_axf = &auth_hash_hmac_ripemd_160; break; case CRYPTO_SHA2_256_HMAC: if ((via_feature_xcrypt & VIA_HAS_SHA) != 0) ses->ses_axf = &padlock_hmac_sha256; else ses->ses_axf = &auth_hash_hmac_sha2_256; break; case CRYPTO_SHA2_384_HMAC: ses->ses_axf = &auth_hash_hmac_sha2_384; break; case CRYPTO_SHA2_512_HMAC: ses->ses_axf = &auth_hash_hmac_sha2_512; break; } /* Allocate memory for HMAC inner and outer contexts. */ ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_PADLOCK, M_ZERO | M_NOWAIT); ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_PADLOCK, M_ZERO | M_NOWAIT); if (ses->ses_ictx == NULL || ses->ses_octx == NULL) return (ENOMEM); /* Setup key if given. */ if (macini->cri_key != NULL) { padlock_hash_key_setup(ses, macini->cri_key, macini->cri_klen); } return (0); } int padlock_hash_process(struct padlock_session *ses, struct cryptodesc *maccrd, struct cryptop *crp) { int error; if ((maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) padlock_hash_key_setup(ses, maccrd->crd_key, maccrd->crd_klen); error = padlock_authcompute(ses, maccrd, crp->crp_buf, crp->crp_flags); return (error); } void padlock_hash_free(struct padlock_session *ses) { if (ses->ses_ictx != NULL) { padlock_free_ctx(ses->ses_axf, ses->ses_ictx); bzero(ses->ses_ictx, ses->ses_axf->ctxsize); free(ses->ses_ictx, M_PADLOCK); ses->ses_ictx = NULL; } if (ses->ses_octx != NULL) { padlock_free_ctx(ses->ses_axf, ses->ses_octx); bzero(ses->ses_octx, ses->ses_axf->ctxsize); free(ses->ses_octx, M_PADLOCK); ses->ses_octx = NULL; } } Index: stable/7/sys/modules/Makefile =================================================================== --- stable/7/sys/modules/Makefile (revision 195685) +++ stable/7/sys/modules/Makefile (revision 195686) @@ -1,656 +1,661 @@ # $FreeBSD$ .include SUBDIR= ${_3dfx} \ ${_3dfx_linux} \ ${_aac} \ accf_data \ accf_http \ ${_acpi} \ ae \ age \ ${_agp} \ aha \ ${_ahb} \ ${_aic} \ aic7xxx \ aio \ ${_amd} \ ${_amdtemp} \ alc \ ale \ amr \ ${_an} \ ${_aout} \ ${_apm} \ ${_ar} \ ${_arcmsr} \ ${_arcnet} \ ${_arl} \ ${_asr} \ ata \ ath \ aue \ ${_auxio} \ ${_awi} \ axe \ bce \ bfe \ bge \ ${_bios} \ ${_bktr} \ ${_bm} \ bridgestp \ cam \ ${_canbepm} \ ${_canbus} \ ${_cardbus} \ ${_cbb} \ cd9660 \ cd9660_iconv \ cdce \ ${_ce} \ ${_ciss} \ ${_cm} \ ${_cmx} \ coda \ coda5 \ ${_coff} \ ${_coretemp} \ ${_cp} \ ${_cpuctl} \ ${_cpufreq} \ ${_crypto} \ ${_cryptodev} \ ${_cs} \ ${_ctau} \ cue \ cxgb \ ${_cx} \ ${_cyclic} \ dc \ dcons \ dcons_crom \ de \ ${_digi} \ ${_dpms} \ ${_dpt} \ ${_drm} \ ${_dtrace} \ dummynet \ ${_ed} \ ${_elink} \ ${_em} \ en \ ${_ep} \ ${_et} \ ${_ex} \ ${_exca} \ ${_ext2fs} \ fatm \ fdc \ fdescfs \ ${_fe} \ firewire \ firmware \ fxp \ gem \ geom \ ${_glxsb} \ hatm \ hifn \ hme \ ${_hptiop} \ ${_hptmv} \ ${_hptrr} \ hwpmc \ ${_i2c} \ ${_ibcs2} \ ${_ichwd} \ ${_ida} \ ${_ie} \ if_bridge \ if_disc \ if_edsc \ if_ef \ if_faith \ if_gif \ if_gre \ if_lagg \ ${_if_ndis} \ if_ppp \ if_sl \ if_stf \ if_tap \ if_tun \ if_vlan \ ${_igb} \ ${_iir} \ ${_io} \ ipdivert \ ${_ipfilter} \ ipfw \ ipfw_nat \ ip_mroute_mod \ ${_ipmi} \ ${_ips} \ ${_ipw} \ ${_ipwfw} \ iscsi \ isp \ ispfw \ ${_iwi} \ ${_iwifw} \ ${_ixgb} \ jme \ joy \ kbdmux \ krpc \ kue \ le \ lge \ libalias \ libiconv \ libmbpool \ libmchain \ ${_linprocfs} \ ${_linsysfs} \ ${_linux} \ lmc \ lpt \ mac_biba \ mac_bsdextended \ mac_ifoff \ mac_lomac \ mac_mls \ mac_none \ mac_partition \ mac_portacl \ mac_seeotheruids \ mac_stub \ mac_test \ malo \ mcd \ md \ mem \ mfi \ mii \ mlx \ ${_mly} \ mmc \ mmcsd \ mpt \ mqueue \ msdosfs \ msdosfs_iconv \ ${_mse} \ msk \ mxge \ my \ ${_ncp} \ ${_ncv} \ ${_ndis} \ netgraph \ ${_nfe} \ nfsclient \ nfslockd \ nfsserver \ nge \ nmdm \ ${_nsp} \ ntfs \ ntfs_iconv \ ${_nxge} \ nullfs \ ${_nve} \ ${_nvram} \ ${_nwfs} \ ${_oltr} \ ${_opensolaris} \ ${_padlock} \ patm \ ${_pccard} \ ${_pcfclock} \ pcn \ ${_pecoff} \ ${_pf} \ ${_pflog} \ plip \ ${_pmc} \ portalfs \ ppbus \ ppc \ ppi \ pps \ procfs \ pseudofs \ ${_pst} \ puc \ ral \ ${_random} \ ${_ray} \ rc \ rc4 \ ${_rdma} \ re \ reiserfs \ rl \ rp \ rue \ rum \ ${_s3} \ ${_safe} \ ${_sbni} \ sbsh \ scc \ scd \ ${_scsi_low} \ sdhci \ sem \ sf \ ${_sio} \ sis \ sk \ ${_smbfs} \ sn \ ${_snc} \ snp \ ${_sound} \ ${_speaker} \ ${_splash} \ ${_sppp} \ ${_sr} \ ste \ ${_stg} \ stge \ ${_streams} \ sym \ ${_syscons} \ sysvipc \ ti \ tl \ ${_tmpfs} \ trm \ ${_twa} \ twe \ tx \ txp \ u3g \ uark \ uart \ ubsa \ ubsec \ ubser \ ucom \ ucycom \ udav \ udbp \ udf \ udf_iconv \ ufm \ ${_ufs} \ ufoma \ uftdi \ ugen \ uhid \ ukbd \ ulpt \ umass \ umct \ umodem \ ums \ unionfs \ uplcom \ ural \ urio \ usb \ uscanner \ uslcom \ utopia \ uvisor \ uvscom \ ${_vesa} \ vge \ vkbd \ ${_vpo} \ vr \ vx \ wb \ ${_wi} \ wlan \ wlan_scan_ap \ wlan_scan_sta \ wlan_acl \ wlan_amrr \ wlan_ccmp \ wlan_tkip \ wlan_wep \ wlan_xauth \ ${_wpi} \ ${_wpifw} \ ${_xe} \ xfs \ xl \ ${_zfs} \ zlib \ zyd .if ${MACHINE_ARCH} != "powerpc" _syscons= syscons _vpo= vpo .endif .if defined(ALL_MODULES) _ufs= ufs .endif .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) .if exists(${.CURDIR}/../opencrypto) _crypto= crypto _cryptodev= cryptodev .endif .if exists(${.CURDIR}/../crypto) _random= random .endif .endif .if ${MK_IPFILTER} != "no" || defined(ALL_MODULES) _ipfilter= ipfilter .endif .if ${MK_PF} != "no" || defined(ALL_MODULES) _pf= pf _pflog= pflog .endif .if ${MACHINE_ARCH} == "i386" # XXX some of these can move to the general case when de-i386'ed # XXX some of these can move now, but are untested on other architectures. _3dfx= 3dfx _3dfx_linux= 3dfx_linux _agp= agp _aic= aic _amd= amd _an= an _aout= aout _apm= apm _ar= ar _arcnet= arcnet _awi= awi _bktr= bktr _cardbus= cardbus _cbb= cbb _ce= ce _coff= coff _cp= cp _cpuctl= cpuctl _cpufreq= cpufreq _cs= cs .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _cyclic= cyclic .endif _digi= digi _dpms= dpms _drm= drm .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _dtrace= dtrace .endif _ed= ed _elink= elink _em= em _ep= ep _et= et _exca= exca _ext2fs= ext2fs _fe= fe _glxsb= glxsb _i2c= i2c _ibcs2= ibcs2 _ie= ie _if_ndis= if_ndis _igb= igb _io= io _linprocfs= linprocfs _linsysfs= linsysfs _linux= linux _mse= mse .if ${MK_NCP} != "no" _ncp= ncp .endif _ncv= ncv _ndis= ndis _nsp= nsp .if ${MK_NCP} != "no" _nwfs= nwfs .endif _oltr= oltr .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _opensolaris= opensolaris .endif _pccard= pccard _pcfclock= pcfclock _pecoff= pecoff _pst= pst _ray= ray _rdma= rdma _safe= safe _sbni= sbni _scsi_low= scsi_low _sio= sio _smbfs= smbfs _sound= sound _speaker= speaker _splash= splash _sppp= sppp _sr= sr _stg= stg _streams= streams _tmpfs= tmpfs _wi= wi _xe= xe .if ${MK_ZFS} != "no" || defined(ALL_MODULES) _zfs= zfs .endif .if ${MACHINE} == "i386" _aac= aac _acpi= acpi _ahb= ahb _amdtemp= amdtemp _arcmsr= arcmsr _arl= arl _asr= asr _bios= bios _ciss= ciss _cm= cm _cmx= cmx _coretemp= coretemp _ctau= ctau _cx= cx _dpt= dpt _ex= ex _hptiop= hptiop _hptmv= hptmv _hptrr= hptrr _ichwd= ichwd _ida= ida _iir= iir _ipmi= ipmi _ips= ips _ipw= ipw _ipwfw= ipwfw _iwi= iwi _iwifw= iwifw _ixgb= ixgb _mly= mly _nfe= nfe _nve= nve _nvram= nvram _nxge= nxge _wpi= wpi _wpifw= wpifw .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) .if exists(${.CURDIR}/../crypto/via) _padlock= padlock .endif .endif _s3= s3 _twa= twa _vesa= vesa .elif ${MACHINE} == "pc98" _canbepm= canbepm _canbus= canbus _pmc= pmc _snc= snc .endif .endif .if ${MACHINE_ARCH} == "amd64" _aac= aac _acpi= acpi _agp= agp _an= an _amdtemp= amdtemp _arcmsr= arcmsr _cardbus= cardbus _cbb= cbb _cmx= cmx _ciss= ciss _coretemp= coretemp _cpuctl= cpuctl _cpufreq= cpufreq .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _cyclic= cyclic .endif _digi= digi _drm= drm .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _dtrace= dtrace .endif _ed= ed _et= et _em= em _exca= exca _ext2fs= ext2fs _hptiop= hptiop _hptmv= hptmv _hptrr= hptrr _i2c= i2c _ichwd= ichwd _ida= ida _if_ndis= if_ndis _igb= igb _iir= iir _io= io _ipmi= ipmi _ips= ips _ipw= ipw _ipwfw= ipwfw _ixgb= ixgb _linprocfs= linprocfs _linsysfs= linsysfs _linux= linux _mly= mly _ndis= ndis _nfe= nfe _nve= nve _nvram= nvram _nxge= nxge .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _opensolaris= opensolaris .endif +.if ${MK_CRYPT} != "no" || defined(ALL_MODULES) +.if exists(${.CURDIR}/../crypto/via) +_padlock= padlock +.endif +.endif _pccard= pccard _rdma= rdma _safe= safe _scsi_low= scsi_low _smbfs= smbfs _sound= sound _speaker= speaker _sppp= sppp _tmpfs= tmpfs _twa= twa _wi= wi _wpi= wpi _wpifw= wpifw .if ${MK_ZFS} != "no" || defined(ALL_MODULES) _zfs= zfs .endif .endif .if ${MACHINE_ARCH} == "ia64" # Modules not enabled on ia64 (as compared to i386) include: # aac acpi aout apm atspeaker drm ibcs2 linprocfs linux ncv # nsp oltr pecoff s3 sbni stg vesa # acpi is not enabled because it is broken as a module on ia64 _aic= aic #_ar= ar not 64-bit clean _arcnet= arcnet _asr= asr _an= an _bktr= bktr _cardbus= cardbus _cbb= cbb _ciss= ciss _cm= cm _cmx= cmx _coff= coff _cpufreq= cpufreq _em= em _ep= ep _exca= exca _fe= fe _igb= igb _iir= iir _mly= mly _pccard= pccard _scsi_low= scsi_low _smbfs= smbfs _sound= sound _splash= splash _sppp= sppp #_sr= sr not 64bit clean _streams= streams _wi= wi _xe= xe .endif .if ${MACHINE_ARCH} == "powerpc" _an= an _bm= bm _nvram= powermac_nvram _smbfs= smbfs .endif .if ${MACHINE_ARCH} == "sparc64" _auxio= auxio _em= em _i2c= i2c _igb= igb .if ${MK_CDDL} != "no" || defined(ALL_MODULES) _opensolaris= opensolaris .endif _sound= sound .if ${MK_ZFS} != "no" || defined(ALL_MODULES) _zfs= zfs .endif .endif .if defined(MODULES_OVERRIDE) && !defined(ALL_MODULES) SUBDIR=${MODULES_OVERRIDE} .endif .for reject in ${WITHOUT_MODULES} SUBDIR:= ${SUBDIR:N${reject}} .endfor # Calling kldxref(8) for each module is expensive. .if !defined(NO_XREF) .MAKEFLAGS+= -DNO_XREF afterinstall: @if type kldxref >/dev/null 2>&1; then \ ${ECHO} kldxref ${DESTDIR}${KMODDIR}; \ kldxref ${DESTDIR}${KMODDIR}; \ fi .endif .include Index: stable/7/sys =================================================================== --- stable/7/sys (revision 195685) +++ stable/7/sys (revision 195686) Property changes on: stable/7/sys ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sys:r187109,187112