MFhead @ r293006

This commit is contained in:
ngie 2015-12-31 21:51:38 +00:00
commit 1ce5880b96
125 changed files with 5943 additions and 2696 deletions

View File

@ -4,7 +4,7 @@
The compilation of software known as FreeBSD is distributed under the
following terms:
Copyright (c) 1992-2015 The FreeBSD Project. All rights reserved.
Copyright (c) 1992-2016 The FreeBSD Project. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -105,6 +105,8 @@ OLD_FILES+=usr/lib/clang/3.7.0/include/xopintrin.h
OLD_FILES+=usr/lib/clang/3.7.0/include/xtestintrin.h
OLD_DIRS+=usr/lib/clang/3.7.0/include
OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-i386.a
OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-preinit-i386.a
OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-preinit-x86_64.a
OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan-x86_64.a
OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan_cxx-i386.a
OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.asan_cxx-x86_64.a

File diff suppressed because it is too large Load Diff

View File

@ -43,12 +43,15 @@ struct arglist {
/*
* expandarg() flags
*/
#define EXP_FULL 0x1 /* perform word splitting & file globbing */
#define EXP_SPLIT 0x1 /* perform word splitting */
#define EXP_TILDE 0x2 /* do normal tilde expansion */
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
#define EXP_SPLIT_LIT 0x20 /* IFS split literal text ${v+-a b c} */
#define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */
#define EXP_GLOB 0x80 /* perform file globbing */
#define EXP_FULL (EXP_SPLIT | EXP_GLOB)
void emptyarglist(struct arglist *);

View File

@ -7720,12 +7720,26 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
refers to is in a different object. We can't tell for
sure yet, because something later might force the
symbol local. */
if (r_type != R_ARM_ABS32
&& r_type != R_ARM_REL32
&& r_type != R_ARM_ABS32_NOI
&& r_type != R_ARM_REL32_NOI
&& r_type != R_ARM_ABS12)
h->needs_plt = 1;
switch (r_type)
{
case R_ARM_ABS12:
case R_ARM_ABS32:
case R_ARM_ABS32_NOI:
case R_ARM_REL32:
case R_ARM_REL32_NOI:
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS:
case R_ARM_MOVW_PREL_NC:
case R_ARM_MOVT_PREL:
case R_ARM_THM_MOVW_ABS_NC:
case R_ARM_THM_MOVT_ABS:
case R_ARM_THM_MOVW_PREL_NC:
case R_ARM_THM_MOVT_PREL:
break;
default:
h->needs_plt = 1;
break;
}
/* If we create a PLT entry, this relocation will reference
it, even if it's an ABS32 relocation. */

View File

@ -1,23 +0,0 @@
This patch adds "CC" and "clang-CC" to the list of program name aliases which
invoke the C++ compiler.
Introduced here: http://svnweb.freebsd.org/changeset/base/257109
Index: tools/clang/tools/driver/driver.cpp
===================================================================
--- tools/clang/tools/driver/driver.cpp
+++ tools/clang/tools/driver/driver.cpp
@@ -213,11 +213,13 @@ static const DriverSuffix *FindDriverSuffix(String
{"clang", nullptr},
{"clang++", "--driver-mode=g++"},
{"clang-c++", "--driver-mode=g++"},
+ {"clang-CC", "--driver-mode=g++"},
{"clang-cc", nullptr},
{"clang-cpp", "--driver-mode=cpp"},
{"clang-g++", "--driver-mode=g++"},
{"clang-gcc", nullptr},
{"clang-cl", "--driver-mode=cl"},
+ {"CC", "--driver-mode=g++"},
{"cc", nullptr},
{"cpp", "--driver-mode=cpp"},
{"cl", "--driver-mode=cl"},

View File

@ -214,13 +214,11 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
{"clang", nullptr},
{"clang++", "--driver-mode=g++"},
{"clang-c++", "--driver-mode=g++"},
{"clang-CC", "--driver-mode=g++"},
{"clang-cc", nullptr},
{"clang-cpp", "--driver-mode=cpp"},
{"clang-g++", "--driver-mode=g++"},
{"clang-gcc", nullptr},
{"clang-cl", "--driver-mode=cl"},
{"CC", "--driver-mode=g++"},
{"cc", nullptr},
{"cpp", "--driver-mode=cpp"},
{"cl", "--driver-mode=cl"},

View File

@ -99,16 +99,7 @@ moreglue(int n)
FILE *p;
size_t align;
/*
* FILE has a mbstate_t variable. This variable tries to be int64_t
* aligned through its definition. int64_t may be larger than void *,
* which is the size traditionally used for ALIGNBYTES. So, use our own
* rounding instead of the MI ALIGN macros. If for some reason
* ALIGNBYTES is larger than int64_t, respect that too. There appears to
* be no portable way to ask for FILE's alignment requirements other
* than just knowing here.
*/
align = MAX(ALIGNBYTES, sizeof(int64_t));
align = __alignof__(FILE);
g = (struct glue *)malloc(sizeof(*g) + align + n * sizeof(FILE));
if (g == NULL)
return (NULL);

View File

@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
.Dd October 20, 2015
.Dd December 29, 2015
.Dt PTRACE 2
.Os
.Sh NAME
@ -372,6 +372,20 @@ The flag is set for first event reported from a new child, which is
automatically attached due to
.Dv PT_FOLLOW_FORK
enabled.
.It PL_FLAG_BORN
This flag is set for the first event reported from a new LWP when LWP
events are enabled via
.Dv PT_LWP_EVENTS .
It is reported along with
.Dv PL_FLAG_SCX
and is always reported if LWP events are enabled.
.It PL_FLAG_EXITED
This flag is set for the last event reported by an exiting LWP when
LWP events are enabled via
.Dv PT_LWP_EVENTS .
Note that this event is not reported when the last LWP in a process exits.
The termination of the last thread is reported via a normal process exit
event.
.El
.It pl_sigmask
The current signal mask of the LWP
@ -463,6 +477,29 @@ Child processes do not inherit this property.
The traced process will set the
.Dv PL_FLAG_FORKED
flag upon exit from a system call that creates a new process.
.It PT_LWP_EVENTS
This request controls tracing of LWP creation and destruction.
If
.Fa data
is non-zero,
then LWPs will stop to report creation and destruction events.
If
.Fa data
is zero,
then LWP creation and destruction events will not be reported.
By default, tracing is not enabled for LWP events.
Child processes do not inherit this property.
New LWPs will stop to report an event with
.Dv PL_FLAG_BORN
set before executing their first instruction.
Exiting LWPs will stop to report an event with
.Dv PL_FLAG_EXITED
set before completing their termination.
.Pp
Note that new processes do not report an event for the creation of their
initial thread,
and exiting processes do not report an event for the termination of the
last thread.
.It PT_VM_TIMESTAMP
This request returns the generation number or timestamp of the memory map of
the traced process as the return value from

View File

@ -59,14 +59,18 @@ MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len)
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
if (fstat(f, &stbuf) < 0)
return 0;
if (fstat(f, &stbuf) < 0) {
i = -1;
goto error;
}
if (ofs > stbuf.st_size)
ofs = stbuf.st_size;
if ((len == 0) || (len > stbuf.st_size - ofs))
len = stbuf.st_size - ofs;
if (lseek(f, ofs, SEEK_SET) < 0)
return 0;
if (lseek(f, ofs, SEEK_SET) < 0) {
i = -1;
goto error;
}
n = len;
i = 0;
while (n > 0) {
@ -79,6 +83,7 @@ MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len)
MDXUpdate(&ctx, buffer, i);
n -= i;
}
error:
e = errno;
close(f);
errno = e;

View File

@ -44,6 +44,12 @@ SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \
.if ${MACHINE_CPUARCH} == "arm"
.PATH: ${LIBC_SRC}/arm/gen
# Do not generate movt/movw, because the relocation fixup for them does not
# translate to the -Bsymbolic -pie format required by self_reloc() in loader(8).
# Also, the fpu is not available in a standalone environment.
CFLAGS.clang+= -mllvm -arm-use-movt=0
CFLAGS.clang+= -mfpu=none
# Compiler support functions
.PATH: ${LIBSTAND_SRC}/../../contrib/compiler-rt/lib/builtins/
# __clzsi2 and ctzsi2 for various builtin functions

View File

@ -76,7 +76,7 @@ main(int argc, char *argv[])
howto = RB_HALT;
} else
howto = 0;
lflag = nflag = qflag = 0;
lflag = nflag = qflag = Nflag = 0;
while ((ch = getopt(argc, argv, "dk:lNnpqr")) != -1)
switch(ch) {
case 'd':

View File

@ -153,46 +153,49 @@ ASENTRY_NP(_start)
* Build page table from scratch.
*/
/* Calculate the physical address of the startup pagetable. */
/*
* Figure out the physical address we're loaded at by assuming this
* entry point code is in the first L1 section and so if we clear the
* offset bits of the pc that will give us the section-aligned load
* address, which remains in r5 throughout all the following code.
*/
ldr r2, =(L1_S_OFFSET)
bic r5, pc, r2
/* Find the delta between VA and PA, result stays in r0 throughout. */
adr r0, Lpagetable
bl translate_va_to_pa
/* Clear boot page table */
mov r1, r0
mov r2, L1_TABLE_SIZE
mov r3,#0
1: str r3, [r1], #4
subs r2, #4
bgt 1b
/*
* Map PA == VA
/*
* First map the entire 4GB address space as VA=PA. It's mapped as
* normal (cached) memory because it's for things like accessing the
* parameters passed in from the bootloader, which might be at any
* physical address, different for every platform.
*/
mov r1, #0
mov r2, #0
mov r3, #4096
bl build_pagetables
/*
* Next we do 64MiB starting at the physical load address, mapped to
* the VA the kernel is linked for.
*/
/* Find the start kernels load address */
adr r5, _start
ldr r2, =(PTE1_OFFSET)
bic r5, r2
mov r1, r5
mov r2, r5
/* Map 64MiB, preserved over calls to build_pagetables */
ldr r2, =(KERNVIRTADDR)
mov r3, #64
bl build_pagetables
/* Create the kernel map to jump to */
mov r1, r5
ldr r2, =(KERNVIRTADDR)
bl build_pagetables
/* Create a device mapping for early_printf if specified. */
#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
/* Create the custom map (1MB) used for early_printf(). */
ldr r1, =SOCDEV_PA
ldr r2, =SOCDEV_VA
mov r3, #1
bl build_pagetables
bl build_device_pagetables
#endif
bl init_mmu
/* Switch to virtual addresses. */
/* Transition the PC from physical to virtual addressing. */
ldr pc, =1f
1:
@ -394,6 +397,15 @@ END(reinit_mmu)
*
* Addresses must be 1MiB aligned
*/
build_device_pagetables:
#if defined(ARM_NEW_PMAP)
ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
#elif defined(SMP)
ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED)
#else
ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
#endif
b 1f
build_pagetables:
/* Set the required page attributed */
#if defined(ARM_NEW_PMAP)
@ -403,18 +415,19 @@ build_pagetables:
#else
ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
#endif
1:
orr r1, r4
/* Move the virtual address to the correct bit location */
lsr r2, #(PTE1_SHIFT - 2)
mov r4, r3
1:
2:
str r1, [r0, r2]
add r2, r2, #4
add r1, r1, #(PTE1_SIZE)
adds r4, r4, #-1
bhi 1b
bhi 2b
mov pc, lr

View File

@ -37,9 +37,12 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <machine/atomic.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
static int ident_lock;
char machine[] = "arm64";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
@ -56,6 +59,7 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
* Aff0 - CPU number in Aff1 cluster
*/
uint64_t __cpu_affinity[MAXCPU];
static u_int cpu_aff_levels;
struct cpu_desc {
u_int cpu_impl;
@ -64,9 +68,32 @@ struct cpu_desc {
u_int cpu_revision;
const char *cpu_impl_name;
const char *cpu_part_name;
uint64_t mpidr;
uint64_t id_aa64afr0;
uint64_t id_aa64afr1;
uint64_t id_aa64dfr0;
uint64_t id_aa64dfr1;
uint64_t id_aa64isar0;
uint64_t id_aa64isar1;
uint64_t id_aa64mmfr0;
uint64_t id_aa64mmfr1;
uint64_t id_aa64pfr0;
uint64_t id_aa64pfr1;
};
struct cpu_desc cpu_desc[MAXCPU];
static u_int cpu_print_regs;
#define PRINT_ID_AA64_AFR0 0x00000001
#define PRINT_ID_AA64_AFR1 0x00000002
#define PRINT_ID_AA64_DFR0 0x00000004
#define PRINT_ID_AA64_DFR1 0x00000008
#define PRINT_ID_AA64_ISAR0 0x00000010
#define PRINT_ID_AA64_ISAR1 0x00000020
#define PRINT_ID_AA64_MMFR0 0x00000040
#define PRINT_ID_AA64_MMFR1 0x00000080
#define PRINT_ID_AA64_PFR0 0x00000100
#define PRINT_ID_AA64_PFR1 0x00000200
struct cpu_parts {
u_int part_id;
@ -124,7 +151,398 @@ const struct cpu_implementers cpu_implementers[] = {
CPU_IMPLEMENTER_NONE,
};
void identify_cpu(void);
void
print_cpu_features(u_int cpu)
{
int printed;
printf("CPU%3d: %s %s r%dp%d", cpu, cpu_desc[cpu].cpu_impl_name,
cpu_desc[cpu].cpu_part_name, cpu_desc[cpu].cpu_variant,
cpu_desc[cpu].cpu_revision);
printf(" affinity:");
switch(cpu_aff_levels) {
default:
case 4:
printf(" %2d", CPU_AFF3(cpu_desc[cpu].mpidr));
/* FALLTHROUGH */
case 3:
printf(" %2d", CPU_AFF2(cpu_desc[cpu].mpidr));
/* FALLTHROUGH */
case 2:
printf(" %2d", CPU_AFF1(cpu_desc[cpu].mpidr));
/* FALLTHROUGH */
case 1:
case 0: /* On UP this will be zero */
printf(" %2d", CPU_AFF0(cpu_desc[cpu].mpidr));
break;
}
printf("\n");
if (cpu != 0 && cpu_print_regs == 0)
return;
#define SEP_STR ((printed++) == 0) ? "" : ","
/* AArch64 Instruction Set Attribute Register 0 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0) {
printed = 0;
printf(" Instruction Set Attributes 0 = <");
switch (ID_AA64ISAR0_AES(cpu_desc[cpu].id_aa64isar0)) {
case ID_AA64ISAR0_AES_NONE:
break;
case ID_AA64ISAR0_AES_BASE:
printf("%sAES", SEP_STR);
break;
case ID_AA64ISAR0_AES_PMULL:
printf("%sAES+PMULL", SEP_STR);
break;
default:
printf("%sUnknown AES", SEP_STR);
break;
}
switch (ID_AA64ISAR0_SHA1(cpu_desc[cpu].id_aa64isar0)) {
case ID_AA64ISAR0_SHA1_NONE:
break;
case ID_AA64ISAR0_SHA1_BASE:
printf("%sSHA1", SEP_STR);
break;
default:
printf("%sUnknown SHA1", SEP_STR);
break;
}
switch (ID_AA64ISAR0_SHA2(cpu_desc[cpu].id_aa64isar0)) {
case ID_AA64ISAR0_SHA2_NONE:
break;
case ID_AA64ISAR0_SHA2_BASE:
printf("%sSHA2", SEP_STR);
break;
default:
printf("%sUnknown SHA2", SEP_STR);
break;
}
switch (ID_AA64ISAR0_CRC32(cpu_desc[cpu].id_aa64isar0)) {
case ID_AA64ISAR0_CRC32_NONE:
break;
case ID_AA64ISAR0_CRC32_BASE:
printf("%sCRC32", SEP_STR);
break;
default:
printf("%sUnknown CRC32", SEP_STR);
break;
}
if ((cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK) != 0)
printf("%s%#lx", SEP_STR,
cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK);
printf(">\n");
}
/* AArch64 Instruction Set Attribute Register 1 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR1) != 0) {
printf(" Instruction Set Attributes 1 = <%#lx>\n",
cpu_desc[cpu].id_aa64isar1);
}
/* AArch64 Processor Feature Register 0 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR0) != 0) {
printed = 0;
printf(" Processor Features 0 = <");
switch (ID_AA64PFR0_GIC(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_GIC_CPUIF_NONE:
break;
case ID_AA64PFR0_GIC_CPUIF_EN:
printf("%sGIC", SEP_STR);
break;
default:
printf("%sUnknown GIC interface", SEP_STR);
break;
}
switch (ID_AA64PFR0_ADV_SIMD(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_ADV_SIMD_NONE:
break;
case ID_AA64PFR0_ADV_SIMD_IMPL:
printf("%sAdvSIMD", SEP_STR);
break;
default:
printf("%sUnknown AdvSIMD", SEP_STR);
break;
}
switch (ID_AA64PFR0_FP(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_FP_NONE:
break;
case ID_AA64PFR0_FP_IMPL:
printf("%sFloat", SEP_STR);
break;
default:
printf("%sUnknown Float", SEP_STR);
break;
}
switch (ID_AA64PFR0_EL3(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_EL3_NONE:
printf("%sNo EL3", SEP_STR);
break;
case ID_AA64PFR0_EL3_64:
printf("%sEL3", SEP_STR);
break;
case ID_AA64PFR0_EL3_64_32:
printf("%sEL3 32", SEP_STR);
break;
default:
printf("%sUnknown EL3", SEP_STR);
break;
}
switch (ID_AA64PFR0_EL2(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_EL2_NONE:
printf("%sNo EL2", SEP_STR);
break;
case ID_AA64PFR0_EL2_64:
printf("%sEL2", SEP_STR);
break;
case ID_AA64PFR0_EL2_64_32:
printf("%sEL2 32", SEP_STR);
break;
default:
printf("%sUnknown EL2", SEP_STR);
break;
}
switch (ID_AA64PFR0_EL1(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_EL1_64:
printf("%sEL1", SEP_STR);
break;
case ID_AA64PFR0_EL1_64_32:
printf("%sEL1 32", SEP_STR);
break;
default:
printf("%sUnknown EL1", SEP_STR);
break;
}
switch (ID_AA64PFR0_EL0(cpu_desc[cpu].id_aa64pfr0)) {
case ID_AA64PFR0_EL0_64:
printf("%sEL0", SEP_STR);
break;
case ID_AA64PFR0_EL0_64_32:
printf("%sEL0 32", SEP_STR);
break;
default:
printf("%sUnknown EL0", SEP_STR);
break;
}
if ((cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK) != 0)
printf("%s%#lx", SEP_STR,
cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK);
printf(">\n");
}
/* AArch64 Processor Feature Register 1 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR1) != 0) {
printf(" Processor Features 1 = <%#lx>\n",
cpu_desc[cpu].id_aa64pfr1);
}
/* AArch64 Memory Model Feature Register 0 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR0) != 0) {
printed = 0;
printf(" Memory Model Features 0 = <");
switch (ID_AA64MMFR0_TGRAN4(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_TGRAN4_NONE:
break;
case ID_AA64MMFR0_TGRAN4_IMPL:
printf("%s4k Granule", SEP_STR);
break;
default:
printf("%sUnknown 4k Granule", SEP_STR);
break;
}
switch (ID_AA64MMFR0_TGRAN16(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_TGRAN16_NONE:
break;
case ID_AA64MMFR0_TGRAN16_IMPL:
printf("%s16k Granule", SEP_STR);
break;
default:
printf("%sUnknown 16k Granule", SEP_STR);
break;
}
switch (ID_AA64MMFR0_TGRAN64(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_TGRAN64_NONE:
break;
case ID_AA64MMFR0_TGRAN64_IMPL:
printf("%s64k Granule", SEP_STR);
break;
default:
printf("%sUnknown 64k Granule", SEP_STR);
break;
}
switch (ID_AA64MMFR0_BIGEND(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_BIGEND_FIXED:
break;
case ID_AA64MMFR0_BIGEND_MIXED:
printf("%sMixedEndian", SEP_STR);
break;
default:
printf("%sUnknown Endian switching", SEP_STR);
break;
}
switch (ID_AA64MMFR0_BIGEND_EL0(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_BIGEND_EL0_FIXED:
break;
case ID_AA64MMFR0_BIGEND_EL0_MIXED:
printf("%sEL0 MixEndian", SEP_STR);
break;
default:
printf("%sUnknown EL0 Endian switching", SEP_STR);
break;
}
switch (ID_AA64MMFR0_S_NS_MEM(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_S_NS_MEM_NONE:
break;
case ID_AA64MMFR0_S_NS_MEM_DISTINCT:
printf("%sS/NS Mem", SEP_STR);
break;
default:
printf("%sUnknown S/NS Mem", SEP_STR);
break;
}
switch (ID_AA64MMFR0_ASID_BITS(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_ASID_BITS_8:
printf("%s8bit ASID", SEP_STR);
break;
case ID_AA64MMFR0_ASID_BITS_16:
printf("%s16bit ASID", SEP_STR);
break;
default:
printf("%sUnknown ASID", SEP_STR);
break;
}
switch (ID_AA64MMFR0_PA_RANGE(cpu_desc[cpu].id_aa64mmfr0)) {
case ID_AA64MMFR0_PA_RANGE_4G:
printf("%s4GB PA", SEP_STR);
break;
case ID_AA64MMFR0_PA_RANGE_64G:
printf("%s64GB PA", SEP_STR);
break;
case ID_AA64MMFR0_PA_RANGE_1T:
printf("%s1TB PA", SEP_STR);
break;
case ID_AA64MMFR0_PA_RANGE_4T:
printf("%s4TB PA", SEP_STR);
break;
case ID_AA64MMFR0_PA_RANGE_16T:
printf("%s16TB PA", SEP_STR);
break;
case ID_AA64MMFR0_PA_RANGE_256T:
printf("%s256TB PA", SEP_STR);
break;
default:
printf("%sUnknown PA Range", SEP_STR);
break;
}
if ((cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK) != 0)
printf("%s%#lx", SEP_STR,
cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK);
printf(">\n");
}
/* AArch64 Memory Model Feature Register 1 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0) {
printf(" Memory Model Features 1 = <%#lx>\n",
cpu_desc[cpu].id_aa64mmfr1);
}
/* AArch64 Debug Feature Register 0 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR0) != 0) {
printed = 0;
printf(" Debug Features 0 = <");
printf("%s%lu CTX Breakpoints", SEP_STR,
ID_AA64DFR0_CTX_CMPS(cpu_desc[cpu].id_aa64dfr0));
printf("%s%lu Watchpoints", SEP_STR,
ID_AA64DFR0_WRPS(cpu_desc[cpu].id_aa64dfr0));
printf("%s%lu Breakpoints", SEP_STR,
ID_AA64DFR0_BRPS(cpu_desc[cpu].id_aa64dfr0));
switch (ID_AA64DFR0_PMU_VER(cpu_desc[cpu].id_aa64dfr0)) {
case ID_AA64DFR0_PMU_VER_NONE:
break;
case ID_AA64DFR0_PMU_VER_3:
printf("%sPMUv3", SEP_STR);
break;
case ID_AA64DFR0_PMU_VER_IMPL:
printf("%sImplementation defined PMU", SEP_STR);
break;
default:
printf("%sUnknown PMU", SEP_STR);
break;
}
switch (ID_AA64DFR0_TRACE_VER(cpu_desc[cpu].id_aa64dfr0)) {
case ID_AA64DFR0_TRACE_VER_NONE:
break;
case ID_AA64DFR0_TRACE_VER_IMPL:
printf("%sTrace", SEP_STR);
break;
default:
printf("%sUnknown Trace", SEP_STR);
break;
}
switch (ID_AA64DFR0_DEBUG_VER(cpu_desc[cpu].id_aa64dfr0)) {
case ID_AA64DFR0_DEBUG_VER_8:
printf("%sDebug v8", SEP_STR);
break;
default:
printf("%sUnknown Debug", SEP_STR);
break;
}
if (cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK)
printf("%s%#lx", SEP_STR,
cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK);
printf(">\n");
}
/* AArch64 Memory Model Feature Register 1 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR1) != 0) {
printf(" Debug Features 1 = <%#lx>\n",
cpu_desc[cpu].id_aa64dfr1);
}
/* AArch64 Auxiliary Feature Register 0 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR0) != 0) {
printf(" Auxiliary Features 0 = <%#lx>\n",
cpu_desc[cpu].id_aa64afr0);
}
/* AArch64 Auxiliary Feature Register 1 */
if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR1) != 0) {
printf(" Auxiliary Features 1 = <%#lx>\n",
cpu_desc[cpu].id_aa64afr1);
}
#undef SEP_STR
}
void
identify_cpu(void)
@ -133,7 +551,6 @@ identify_cpu(void)
u_int impl_id;
u_int part_id;
u_int cpu;
uint64_t mpidr;
size_t i;
const struct cpu_parts *cpu_partsp = NULL;
@ -171,19 +588,77 @@ identify_cpu(void)
cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
/* Save affinity for current CPU */
mpidr = get_mpidr();
CPU_AFFINITY(cpu) = mpidr & CPU_AFF_MASK;
cpu_desc[cpu].mpidr = get_mpidr();
CPU_AFFINITY(cpu) = cpu_desc[cpu].mpidr & CPU_AFF_MASK;
/* Print details for boot CPU or if we want verbose output */
if (cpu == 0 || bootverbose) {
printf("CPU(%d): %s %s r%dp%d\n", cpu,
cpu_desc[cpu].cpu_impl_name,
cpu_desc[cpu].cpu_part_name,
cpu_desc[cpu].cpu_variant,
cpu_desc[cpu].cpu_revision);
cpu_desc[cpu].id_aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
cpu_desc[cpu].id_aa64dfr1 = READ_SPECIALREG(id_aa64dfr1_el1);
cpu_desc[cpu].id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
cpu_desc[cpu].id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1);
cpu_desc[cpu].id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1);
cpu_desc[cpu].id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
cpu_desc[cpu].id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
cpu_desc[cpu].id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
if (cpu != 0) {
/*
* This code must run on one cpu at a time, but we are
* not scheduling on the current core so implement a
* simple spinlock.
*/
while (atomic_cmpset_acq_int(&ident_lock, 0, 1) == 0)
__asm __volatile("wfe" ::: "memory");
switch (cpu_aff_levels) {
case 0:
if (CPU_AFF0(cpu_desc[cpu].mpidr) !=
CPU_AFF0(cpu_desc[0].mpidr))
cpu_aff_levels = 1;
/* FALLTHROUGH */
case 1:
if (CPU_AFF1(cpu_desc[cpu].mpidr) !=
CPU_AFF1(cpu_desc[0].mpidr))
cpu_aff_levels = 2;
/* FALLTHROUGH */
case 2:
if (CPU_AFF2(cpu_desc[cpu].mpidr) !=
CPU_AFF2(cpu_desc[0].mpidr))
cpu_aff_levels = 3;
/* FALLTHROUGH */
case 3:
if (CPU_AFF3(cpu_desc[cpu].mpidr) !=
CPU_AFF3(cpu_desc[0].mpidr))
cpu_aff_levels = 4;
break;
}
if (cpu_desc[cpu].id_aa64afr0 != cpu_desc[0].id_aa64afr0)
cpu_print_regs |= PRINT_ID_AA64_AFR0;
if (cpu_desc[cpu].id_aa64afr1 != cpu_desc[0].id_aa64afr1)
cpu_print_regs |= PRINT_ID_AA64_AFR1;
if (cpu_desc[cpu].id_aa64dfr0 != cpu_desc[0].id_aa64dfr0)
cpu_print_regs |= PRINT_ID_AA64_DFR0;
if (cpu_desc[cpu].id_aa64dfr1 != cpu_desc[0].id_aa64dfr1)
cpu_print_regs |= PRINT_ID_AA64_DFR1;
if (cpu_desc[cpu].id_aa64isar0 != cpu_desc[0].id_aa64isar0)
cpu_print_regs |= PRINT_ID_AA64_ISAR0;
if (cpu_desc[cpu].id_aa64isar1 != cpu_desc[0].id_aa64isar1)
cpu_print_regs |= PRINT_ID_AA64_ISAR1;
if (cpu_desc[cpu].id_aa64mmfr0 != cpu_desc[0].id_aa64mmfr0)
cpu_print_regs |= PRINT_ID_AA64_MMFR0;
if (cpu_desc[cpu].id_aa64mmfr1 != cpu_desc[0].id_aa64mmfr1)
cpu_print_regs |= PRINT_ID_AA64_MMFR1;
if (cpu_desc[cpu].id_aa64pfr0 != cpu_desc[0].id_aa64pfr0)
cpu_print_regs |= PRINT_ID_AA64_PFR0;
if (cpu_desc[cpu].id_aa64pfr1 != cpu_desc[0].id_aa64pfr1)
cpu_print_regs |= PRINT_ID_AA64_PFR1;
/* Wake up the other CPUs */
atomic_store_rel_int(&ident_lock, 0);
__asm __volatile("sev" ::: "memory");
}
if (bootverbose)
printf("CPU%u affinity: %u.%u.%u.%u\n", 0, CPU_AFF0(mpidr),
CPU_AFF1(mpidr), CPU_AFF2(mpidr), CPU_AFF3(mpidr));
}

View File

@ -175,7 +175,7 @@ arm64_cpu_attach(device_t dev)
static void
release_aps(void *dummy __unused)
{
int i;
int cpu, i;
/* Setup the IPI handler */
for (i = 0; i < COUNT_IPI; i++)
@ -188,8 +188,14 @@ release_aps(void *dummy __unused)
printf("Release APs\n");
for (i = 0; i < 2000; i++) {
if (smp_started)
if (smp_started) {
for (cpu = 0; cpu <= mp_maxid; cpu++) {
if (CPU_ABSENT(cpu))
continue;
print_cpu_features(cpu);
}
return;
}
DELAY(1000);
}

View File

@ -121,19 +121,147 @@
/* ICC_SRE_EL2 */
#define ICC_SRE_EL2_EN (1U << 3)
/* ID_AA64DFR0_EL1 */
#define ID_AA64DFR0_MASK 0xf0f0ffff
#define ID_AA64DFR0_DEBUG_VER_SHIFT 0
#define ID_AA64DFR0_DEBUG_VER_MASK (0xf << ID_AA64DFR0_DEBUG_VER_SHIFT)
#define ID_AA64DFR0_DEBUG_VER(x) ((x) & ID_AA64DFR0_DEBUG_VER_MASK)
#define ID_AA64DFR0_DEBUG_VER_8 (0x6 << ID_AA64DFR0_DEBUG_VER_SHIFT)
#define ID_AA64DFR0_TRACE_VER_SHIFT 4
#define ID_AA64DFR0_TRACE_VER_MASK (0xf << ID_AA64DFR0_TRACE_VER_SHIFT)
#define ID_AA64DFR0_TRACE_VER(x) ((x) & ID_AA64DFR0_TRACE_VER_MASK)
#define ID_AA64DFR0_TRACE_VER_NONE (0x0 << ID_AA64DFR0_TRACE_VER_SHIFT)
#define ID_AA64DFR0_TRACE_VER_IMPL (0x1 << ID_AA64DFR0_TRACE_VER_SHIFT)
#define ID_AA64DFR0_PMU_VER_SHIFT 8
#define ID_AA64DFR0_PMU_VER_MASK (0xf << ID_AA64DFR0_PMU_VER_SHIFT)
#define ID_AA64DFR0_PMU_VER(x) ((x) & ID_AA64DFR0_PMU_VER_MASK)
#define ID_AA64DFR0_PMU_VER_NONE (0x0 << ID_AA64DFR0_PMU_VER_SHIFT)
#define ID_AA64DFR0_PMU_VER_3 (0x1 << ID_AA64DFR0_PMU_VER_SHIFT)
#define ID_AA64DFR0_PMU_VER_IMPL (0xf << ID_AA64DFR0_PMU_VER_SHIFT)
#define ID_AA64DFR0_BRPS_SHIFT 12
#define ID_AA64DFR0_BRPS_MASK (0xf << ID_AA64DFR0_BRPS_SHIFT)
#define ID_AA64DFR0_BRPS(x) \
((((x) >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) + 1)
#define ID_AA64DFR0_WRPS_SHIFT 20
#define ID_AA64DFR0_WRPS_MASK (0xf << ID_AA64DFR0_WRPS_SHIFT)
#define ID_AA64DFR0_WRPS(x) \
((((x) >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) + 1)
#define ID_AA64DFR0_CTX_CMPS_SHIFT 28
#define ID_AA64DFR0_CTX_CMPS_MASK (0xf << ID_AA64DFR0_CTX_CMPS_SHIFT)
#define ID_AA64DFR0_CTX_CMPS(x) \
((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1)
/* ID_AA64ISAR0_EL1 */
#define ID_AA64ISAR0_MASK 0x000ffff0
#define ID_AA64ISAR0_AES_SHIFT 4
#define ID_AA64ISAR0_AES_MASK (0xf << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK)
#define ID_AA64ISAR0_AES_NONE (0x0 << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_AES_BASE (0x1 << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_AES_PMULL (0x2 << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_SHA1_SHIFT 8
#define ID_AA64ISAR0_SHA1_MASK (0xf << ID_AA64ISAR0_SHA1_SHIFT)
#define ID_AA64ISAR0_SHA1(x) ((x) & ID_AA64ISAR0_SHA1_MASK)
#define ID_AA64ISAR0_SHA1_NONE (0x0 << ID_AA64ISAR0_SHA1_SHIFT)
#define ID_AA64ISAR0_SHA1_BASE (0x1 << ID_AA64ISAR0_SHA1_SHIFT)
#define ID_AA64ISAR0_SHA2_SHIFT 12
#define ID_AA64ISAR0_SHA2_MASK (0xf << ID_AA64ISAR0_SHA2_SHIFT)
#define ID_AA64ISAR0_SHA2(x) ((x) & ID_AA64ISAR0_SHA2_MASK)
#define ID_AA64ISAR0_SHA2_NONE (0x0 << ID_AA64ISAR0_SHA2_SHIFT)
#define ID_AA64ISAR0_SHA2_BASE (0x1 << ID_AA64ISAR0_SHA2_SHIFT)
#define ID_AA64ISAR0_CRC32_SHIFT 16
#define ID_AA64ISAR0_CRC32_MASK (0xf << ID_AA64ISAR0_CRC32_SHIFT)
#define ID_AA64ISAR0_CRC32(x) ((x) & ID_AA64ISAR0_CRC32_MASK)
#define ID_AA64ISAR0_CRC32_NONE (0x0 << ID_AA64ISAR0_CRC32_SHIFT)
#define ID_AA64ISAR0_CRC32_BASE (0x1 << ID_AA64ISAR0_CRC32_SHIFT)
/* ID_AA64MMFR0_EL1 */
#define ID_AA64MMFR0_MASK 0xffffffff
#define ID_AA64MMFR0_PA_RANGE_SHIFT 0
#define ID_AA64MMFR0_PA_RANGE_MASK (0xf << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_PA_RANGE(x) ((x) & ID_AA64MMFR0_PA_RANGE_MASK)
#define ID_AA64MMFR0_PA_RANGE_4G (0x0 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_PA_RANGE_64G (0x1 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_PA_RANGE_1T (0x2 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_PA_RANGE_4T (0x3 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_PA_RANGE_16T (0x4 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_PA_RANGE_256T (0x5 << ID_AA64MMFR0_PA_RANGE_SHIFT)
#define ID_AA64MMFR0_ASID_BITS_SHIFT 4
#define ID_AA64MMFR0_ASID_BITS_MASK (0xf << ID_AA64MMFR0_ASID_BITS_SHIFT)
#define ID_AA64MMFR0_ASID_BITS(x) ((x) & ID_AA64MMFR0_ASID_BITS_MASK)
#define ID_AA64MMFR0_ASID_BITS_8 (0x0 << ID_AA64MMFR0_ASID_BITS_SHIFT)
#define ID_AA64MMFR0_ASID_BITS_16 (0x2 << ID_AA64MMFR0_ASID_BITS_SHIFT)
#define ID_AA64MMFR0_BIGEND_SHIFT 8
#define ID_AA64MMFR0_BIGEND_MASK (0xf << ID_AA64MMFR0_BIGEND_SHIFT)
#define ID_AA64MMFR0_BIGEND(x) ((x) & ID_AA64MMFR0_BIGEND_MASK)
#define ID_AA64MMFR0_BIGEND_FIXED (0x0 << ID_AA64MMFR0_BIGEND_SHIFT)
#define ID_AA64MMFR0_BIGEND_MIXED (0x1 << ID_AA64MMFR0_BIGEND_SHIFT)
#define ID_AA64MMFR0_S_NS_MEM_SHIFT 12
#define ID_AA64MMFR0_S_NS_MEM_MASK (0xf << ID_AA64MMFR0_S_NS_MEM_SHIFT)
#define ID_AA64MMFR0_S_NS_MEM(x) ((x) & ID_AA64MMFR0_S_NS_MEM_MASK)
#define ID_AA64MMFR0_S_NS_MEM_NONE (0x0 << ID_AA64MMFR0_S_NS_MEM_SHIFT)
#define ID_AA64MMFR0_S_NS_MEM_DISTINCT (0x1 << ID_AA64MMFR0_S_NS_MEM_SHIFT)
#define ID_AA64MMFR0_BIGEND_EL0_SHIFT 16
#define ID_AA64MMFR0_BIGEND_EL0_MASK (0xf << ID_AA64MMFR0_BIGEND_EL0_SHIFT)
#define ID_AA64MMFR0_BIGEND_EL0(x) ((x) & ID_AA64MMFR0_BIGEND_EL0_MASK)
#define ID_AA64MMFR0_BIGEND_EL0_FIXED (0x0 << ID_AA64MMFR0_BIGEND_EL0_SHIFT)
#define ID_AA64MMFR0_BIGEND_EL0_MIXED (0x1 << ID_AA64MMFR0_BIGEND_EL0_SHIFT)
#define ID_AA64MMFR0_TGRAN16_SHIFT 20
#define ID_AA64MMFR0_TGRAN16_MASK (0xf << ID_AA64MMFR0_TGRAN16_SHIFT)
#define ID_AA64MMFR0_TGRAN16(x) ((x) & ID_AA64MMFR0_TGRAN16_MASK)
#define ID_AA64MMFR0_TGRAN16_NONE (0x0 << ID_AA64MMFR0_TGRAN16_SHIFT)
#define ID_AA64MMFR0_TGRAN16_IMPL (0x1 << ID_AA64MMFR0_TGRAN16_SHIFT)
#define ID_AA64MMFR0_TGRAN64_SHIFT 24
#define ID_AA64MMFR0_TGRAN64_MASK (0xf << ID_AA64MMFR0_TGRAN64_SHIFT)
#define ID_AA64MMFR0_TGRAN64(x) ((x) & ID_AA64MMFR0_TGRAN64_MASK)
#define ID_AA64MMFR0_TGRAN64_IMPL (0x0 << ID_AA64MMFR0_TGRAN64_SHIFT)
#define ID_AA64MMFR0_TGRAN64_NONE (0xf << ID_AA64MMFR0_TGRAN64_SHIFT)
#define ID_AA64MMFR0_TGRAN4_SHIFT 28
#define ID_AA64MMFR0_TGRAN4_MASK (0xf << ID_AA64MMFR0_TGRAN4_SHIFT)
#define ID_AA64MMFR0_TGRAN4(x) ((x) & ID_AA64MMFR0_TGRAN4_MASK)
#define ID_AA64MMFR0_TGRAN4_IMPL (0x0 << ID_AA64MMFR0_TGRAN4_SHIFT)
#define ID_AA64MMFR0_TGRAN4_NONE (0xf << ID_AA64MMFR0_TGRAN4_SHIFT)
/* ID_AA64PFR0_EL1 */
#define ID_AA64PFR0_EL0_MASK (0xf << 0)
#define ID_AA64PFR0_EL1_MASK (0xf << 4)
#define ID_AA64PFR0_EL2_MASK (0xf << 8)
#define ID_AA64PFR0_EL3_MASK (0xf << 12)
#define ID_AA64PFR0_FP_MASK (0xf << 16)
#define ID_AA64PFR0_FP_IMPL (0x0 << 16) /* Floating-point implemented */
#define ID_AA64PFR0_FP_NONE (0xf << 16) /* Floating-point not implemented */
#define ID_AA64PFR0_ADV_SIMD_MASK (0xf << 20)
#define ID_AA64PFR0_GIC_SHIFT (24)
#define ID_AA64PFR0_GIC_BITS (0x4) /* Number of bits in GIC field */
#define ID_AA64PFR0_GIC_MASK (0xf << ID_AA64PFR0_GIC_SHIFT)
#define ID_AA64PFR0_GIC_CPUIF_EN (0x1 << ID_AA64PFR0_GIC_SHIFT)
#define ID_AA64PFR0_MASK 0x0fffffff
#define ID_AA64PFR0_EL0_SHIFT 0
#define ID_AA64PFR0_EL0_MASK (0xf << ID_AA64PFR0_EL0_SHIFT)
#define ID_AA64PFR0_EL0(x) ((x) & ID_AA64PFR0_EL0_MASK)
#define ID_AA64PFR0_EL0_64 (1 << ID_AA64PFR0_EL0_SHIFT)
#define ID_AA64PFR0_EL0_64_32 (2 << ID_AA64PFR0_EL0_SHIFT)
#define ID_AA64PFR0_EL1_SHIFT 4
#define ID_AA64PFR0_EL1_MASK (0xf << ID_AA64PFR0_EL1_SHIFT)
#define ID_AA64PFR0_EL1(x) ((x) & ID_AA64PFR0_EL1_MASK)
#define ID_AA64PFR0_EL1_64 (1 << ID_AA64PFR0_EL1_SHIFT)
#define ID_AA64PFR0_EL1_64_32 (2 << ID_AA64PFR0_EL1_SHIFT)
#define ID_AA64PFR0_EL2_SHIFT 8
#define ID_AA64PFR0_EL2_MASK (0xf << ID_AA64PFR0_EL2_SHIFT)
#define ID_AA64PFR0_EL2(x) ((x) & ID_AA64PFR0_EL2_MASK)
#define ID_AA64PFR0_EL2_NONE (0 << ID_AA64PFR0_EL2_SHIFT)
#define ID_AA64PFR0_EL2_64 (1 << ID_AA64PFR0_EL2_SHIFT)
#define ID_AA64PFR0_EL2_64_32 (2 << ID_AA64PFR0_EL2_SHIFT)
#define ID_AA64PFR0_EL3_SHIFT 12
#define ID_AA64PFR0_EL3_MASK (0xf << ID_AA64PFR0_EL3_SHIFT)
#define ID_AA64PFR0_EL3(x) ((x) & ID_AA64PFR0_EL3_MASK)
#define ID_AA64PFR0_EL3_NONE (0 << ID_AA64PFR0_EL3_SHIFT)
#define ID_AA64PFR0_EL3_64 (1 << ID_AA64PFR0_EL3_SHIFT)
#define ID_AA64PFR0_EL3_64_32 (2 << ID_AA64PFR0_EL3_SHIFT)
#define ID_AA64PFR0_FP_SHIFT 16
#define ID_AA64PFR0_FP_MASK (0xf << ID_AA64PFR0_FP_SHIFT)
#define ID_AA64PFR0_FP(x) ((x) & ID_AA64PFR0_FP_MASK)
#define ID_AA64PFR0_FP_IMPL (0x0 << ID_AA64PFR0_FP_SHIFT)
#define ID_AA64PFR0_FP_NONE (0xf << ID_AA64PFR0_FP_SHIFT)
#define ID_AA64PFR0_ADV_SIMD_SHIFT 20
#define ID_AA64PFR0_ADV_SIMD_MASK (0xf << ID_AA64PFR0_ADV_SIMD_SHIFT)
#define ID_AA64PFR0_ADV_SIMD(x) ((x) & ID_AA64PFR0_ADV_SIMD_MASK)
#define ID_AA64PFR0_ADV_SIMD_IMPL (0x0 << ID_AA64PFR0_ADV_SIMD_SHIFT)
#define ID_AA64PFR0_ADV_SIMD_NONE (0xf << ID_AA64PFR0_ADV_SIMD_SHIFT)
#define ID_AA64PFR0_GIC_BITS 0x4 /* Number of bits in GIC field */
#define ID_AA64PFR0_GIC_SHIFT 24
#define ID_AA64PFR0_GIC_MASK (0xf << ID_AA64PFR0_GIC_SHIFT)
#define ID_AA64PFR0_GIC(x) ((x) & ID_AA64PFR0_GIC_MASK)
#define ID_AA64PFR0_GIC_CPUIF_NONE (0x0 << ID_AA64PFR0_GIC_SHIFT)
#define ID_AA64PFR0_GIC_CPUIF_EN (0x1 << ID_AA64PFR0_GIC_SHIFT)
/* MAIR_EL1 - Memory Attribute Indirection Register */
#define MAIR_ATTR_MASK(idx) (0xff << ((n)* 8))

View File

@ -145,6 +145,7 @@ void cpu_halt(void) __dead2;
void cpu_reset(void) __dead2;
void fork_trampoline(void);
void identify_cpu(void);
void print_cpu_features(u_int);
void swi_vm(void *v);
#define CPU_AFFINITY(cpu) __cpu_affinity[(cpu)]

View File

@ -90,6 +90,7 @@ ram_blacklist_type="ram_blacklist" # Required for the kernel to find
#password="" # Prevent changes to boot options
#bootlock_password="" # Prevent booting (see check-password.4th(8))
#geom_eli_passphrase_prompt="NO" # Prompt for geli(8) passphrase to mount root
bootenv_autolist="YES" # Auto populate the list of ZFS Boot Environments
#beastie_disable="NO" # Turn the beastie boot menu on and off
#kernels="kernel kernel.old" # Kernels to display in the boot menu
#loader_logo="orbbw" # Desired logo: orbbw, orb, fbsdbw, beastiebw, beastie, none

View File

@ -351,4 +351,68 @@ also menu-namespace also menu-command-helpers
2 goto_menu
;
\
\ Set boot environment defaults
\
: init_bootenv ( -- )
s" set menu_caption[1]=${bemenu_current}${vfs.root.mountfrom}" evaluate
s" set ansi_caption[1]=${beansi_current}${vfs.root.mountfrom}" evaluate
s" set menu_caption[2]=${bemenu_bootfs}${zfs_be_active}" evaluate
s" set ansi_caption[2]=${beansi_bootfs}${zfs_be_active}" evaluate
s" set menu_caption[3]=${bemenu_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
s" set ansi_caption[3]=${beansi_page}${zfs_be_currpage}${bemenu_pageof}${zfs_be_pages}" evaluate
;
\
\ Redraw the entire screen. A long BE name can corrupt the menu
\
: be_draw_screen
clear \ Clear the screen (in screen.4th)
print_version \ print version string (bottom-right; see version.4th)
draw-beastie \ Draw FreeBSD logo at right (in beastie.4th)
draw-brand \ Draw brand.4th logo at top (in brand.4th)
menu-init \ Initialize menu and draw bounding box (in menu.4th)
;
\
\ Select a boot environment
\
: set_bootenv ( N -- N TRUE )
dup s" set vfs.root.mountfrom=${bootenv_root[E]}" 38 +c! evaluate
s" set currdev=${vfs.root.mountfrom}:" evaluate
s" unload" evaluate
free-module-options
s" /boot/defaults/loader.conf" read-conf
s" /boot/loader.conf" read-conf
s" /boot/loader.conf.local" read-conf
init_bootenv
be_draw_screen
menu-redraw
TRUE
;
\
\ Switch to the next page of boot environments
\
: set_be_page ( N -- N TRUE )
s" zfs_be_currpage" getenv dup -1 = if
drop s" 1"
else
0 s>d 2swap
>number ( ud caddr/u -- ud' caddr'/u' ) \ convert string to numbers
2drop \ drop the string
1 um/mod ( ud u1 -- u2 u3 ) \ convert double ud' to single u3' and remainder u2
swap drop ( ud2 u3 -- u3 ) \ drop the remainder u2
1+ \ increment the page number
s>d <# #s #> \ convert back to a string
then
s" zfs_be_currpage" setenv
s" reloadbe" evaluate
3 goto_menu
;
only forth definitions

View File

@ -68,6 +68,13 @@ set mainmenu_command[6]="2 goto_menu"
set mainmenu_keycode[6]=111
set mainansi_caption[6]="Configure Boot ^[1mO^[mptions..."
s" currdev" getenv dup 0> [if] drop 4 s" zfs:" compare 0= [if]
set mainmenu_caption[7]="Select Boot [E]nvironment..."
set mainmenu_command[7]="3 goto_menu"
set mainmenu_keycode[7]=101
set mainansi_caption[7]="Select Boot ^[1mE^[37mnvironment..."
[then] [else] drop [then]
\
\ BOOT OPTIONS MENU
\
@ -119,6 +126,37 @@ set optionsmenu_keycode[6]=118
set optionsansi_caption[6]="^[1mV^[merbose..... ^[34;1mOff^[m"
set optionstoggled_ansi[6]="^[1mV^[merbose..... ^[32;7mOn^[m"
\
\ BOOT ENVIRONMENT MENU
\
set menuset_name3="bootenv"
set bemenu_current="Active: "
set beansi_current="^[1m${bemenu_current}^[m"
set bemenu_bootfs="bootfs: "
set beansi_bootfs="^[1m${bemenu_bootfs}^[m"
set bemenu_page="[P]age: "
set beansi_page="^[1mP^[mage: "
set bemenu_pageof=" of "
set beansi_pageof="${bemenu_pageof}"
set zfs_be_currpage=1
set bootenvmenu_init="init_bootenv"
set bootenvmenu_command[1]="be_draw_screen 1 goto_menu"
set bootenvmenu_keycode[1]=8
set bootenvmenu_command[2]="set_bootenv"
set bootenvmenu_keycode[2]=97
set bootenv_root[2]="${zfs_be_active}"
set bootenvmenu_command[3]="set_be_page"
set bootenvmenu_keycode[3]=112
set bootenvmenu_options=4
set bootenvmenu_optionstext="Boot Environments:"
\ Enable automatic booting (add ``autoboot_delay=N'' to loader.conf(5) to
\ customize the timeout; default is 10-seconds)
\
@ -128,6 +166,21 @@ set menu_timeout_command="boot"
\
try-include /boot/menu.rc.local
\ Initialize boot environment variables
\
s" reloadbe" sfind ( xt|0 bool ) [if]
s" bootenv_autolist" getenv dup -1 = [if]
drop s" execute" evaluate \ Use evaluate to avoid passing
\ reloadbe an optional parameter
[else]
s" YES" compare-insensitive 0= [if]
s" execute" evaluate
[then]
[then]
[else]
drop ( xt=0 )
[then]
\ Display the main menu (see `menu.4th')
set menuset_initial=1
menuset-loadinitial

View File

@ -684,7 +684,7 @@ only forth also support-functions also file-processing definitions
s" loader_conf_files" getenv conf_files string=
;
: set_nextboot_conf \ XXX maybe do as set_conf_files ?
: set_nextboot_conf
value_buffer strget unquote nextboot_conf_file string=
;
@ -833,7 +833,7 @@ get-current ( -- wid ) previous definitions >search ( wid -- )
repeat
;
: peek_file
: peek_file ( addr len -- )
0 to end_of_file?
reset_line_reading
O_RDONLY fopen fd !
@ -844,6 +844,7 @@ get-current ( -- wid ) previous definitions >search ( wid -- )
['] process_assignment catch
['] free_buffers catch
fd @ fclose
swap throw throw
;
only forth also support-functions definitions
@ -851,7 +852,6 @@ only forth also support-functions definitions
\ Interface to loading conf files
: load_conf ( addr len -- )
\ ." ----- Trying conf " 2dup type cr \ debugging
0 to end_of_file?
reset_line_reading
O_RDONLY fopen fd !
@ -930,6 +930,30 @@ only forth definitions also support-functions
repeat
;
: free-one-module { addr -- addr }
addr module.name strfree
addr module.loadname strfree
addr module.type strfree
addr module.args strfree
addr module.beforeload strfree
addr module.afterload strfree
addr module.loaderror strfree
addr
;
: free-module-options
module_options @
begin
?dup
while
free-one-module
dup module.next @
swap free-memory
repeat
0 module_options !
0 last_module_option !
;
only forth also support-functions definitions
\ Variables used for processing multiple conf files
@ -943,7 +967,6 @@ string current_file_name_ref \ used to print the file name
\ loader_conf_files processing support functions
: get_conf_files ( -- addr len ) \ put addr/len on stack, reset var
\ ." -- starting on <" conf_files strtype ." >" cr \ debugging
conf_files strget 0 0 conf_files strset
;
@ -970,7 +993,6 @@ string current_file_name_ref \ used to print the file name
pos char+ to pos
repeat
addr len pos addr r@ + pos r> -
\ 2dup ." get_file_name has " type cr \ debugging
;
: get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 )
@ -1021,25 +1043,26 @@ string current_file_name_ref \ used to print the file name
;
: get_nextboot_conf_file ( -- addr len )
nextboot_conf_file strget strdup \ XXX is the strdup a leak ?
nextboot_conf_file strget
;
: rewrite_nextboot_file ( -- )
get_nextboot_conf_file
O_WRONLY fopen fd !
fd @ -1 = if EOPEN throw then
fd @ s' nextboot_enable="NO" ' fwrite
fd @ s' nextboot_enable="NO" ' fwrite ( fd buf len -- nwritten ) drop
fd @ fclose
;
: include_nextboot_file
: include_nextboot_file ( -- )
get_nextboot_conf_file
['] peek_file catch
['] peek_file catch if 2drop then
nextboot? if
get_nextboot_conf_file
current_file_name_ref strref
['] load_conf catch
process_conf_errors
['] rewrite_nextboot_file catch
['] rewrite_nextboot_file catch if 2drop then
then
;

View File

@ -69,6 +69,7 @@ static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
#ifdef LOADER_ZFS_SUPPORT
static void init_zfs_bootenv(char *currdev);
static void i386_zfs_probe(void);
#endif
@ -294,12 +295,40 @@ extract_currdev(void)
new_currdev.d_unit = 0;
}
#ifdef LOADER_ZFS_SUPPORT
init_zfs_bootenv(zfs_fmtdev(&new_currdev));
#endif
env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
i386_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
env_nounset);
}
#ifdef LOADER_ZFS_SUPPORT
static void
init_zfs_bootenv(char *currdev)
{
char *beroot;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
/* Do not overwrite if already set */
setenv("vfs.root.mountfrom", currdev, 0);
/* Forward past zfs: */
currdev = strchr(currdev, ':');
currdev++;
/* Remove the last element (current bootenv) */
beroot = strrchr(currdev, '/');
beroot[0] = '\0';
beroot = currdev;
setenv("zfs_be_root", beroot, 1);
}
#endif
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
@ -353,6 +382,34 @@ command_lszfs(int argc, char *argv[])
command_errmsg = strerror(err);
return (CMD_ERROR);
}
return (CMD_OK);
}
COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
command_reloadbe);
static int
command_reloadbe(int argc, char *argv[])
{
int err;
if (argc > 2) {
command_errmsg = "wrong number of arguments";
return (CMD_ERROR);
}
if (argc == 2) {
err = zfs_bootenv(argv[1]);
} else {
err = zfs_bootenv(getenv("zfs_be_root"));
}
if (err != 0) {
command_errmsg = strerror(err);
return (CMD_ERROR);
}
return (CMD_OK);
}
#endif

View File

@ -585,6 +585,10 @@ handle_uboot_env_var(enum ubenv_action action, const char * var)
*/
if (action == UBENV_IMPORT) {
len = strcspn(var, "=");
if (len == 0) {
printf("name cannot start with '=': '%s'\n", var);
return;
}
if (var[len] == 0) {
strcpy(ldvar, "uboot.");
strncat(ldvar, var, sizeof(ldvar) - 7);
@ -604,9 +608,11 @@ handle_uboot_env_var(enum ubenv_action action, const char * var)
var = &var[6];
}
/* If ldvar is malformed or there's no variable name left, punt. */
if (ldvar[0] == 0 || var[0] == 0)
/* If there is no variable name left, punt. */
if (var[0] == 0) {
printf("empty variable name\n");
return;
}
val = ub_env_get(var);
if (action == UBENV_SHOW) {

View File

@ -62,6 +62,9 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
char *zfs_fmtdev(void *vdev);
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
int zfs_bootenv(const char *name);
int zfs_belist_add(const char *name);
int zfs_set_env(void);
extern struct devsw zfs_dev;
extern struct fs_ops zfs_fsops;

View File

@ -48,6 +48,10 @@ __FBSDID("$FreeBSD$");
#include "zfsimpl.c"
/* Define the range of indexes to be populated with ZFS Boot Environments */
#define ZFS_BE_FIRST 4
#define ZFS_BE_LAST 8
static int zfs_open(const char *path, struct open_file *f);
static int zfs_write(struct open_file *f, void *buf, size_t size, size_t *resid);
static int zfs_close(struct open_file *f);
@ -80,6 +84,16 @@ struct file {
zap_leaf_phys_t *f_zap_leaf; /* zap leaf buffer */
};
static int zfs_env_index;
static int zfs_env_count;
SLIST_HEAD(zfs_be_list, zfs_be_entry) zfs_be_head = SLIST_HEAD_INITIALIZER(zfs_be_head);
struct zfs_be_list *zfs_be_headp;
struct zfs_be_entry {
const char *name;
SLIST_ENTRY(zfs_be_entry) entries;
} *zfs_be, *zfs_be_tmp;
/*
* Open a file.
*/
@ -691,6 +705,156 @@ zfs_list(const char *name)
rv = zfs_lookup_dataset(spa, dsname, &objid);
if (rv != 0)
return (rv);
rv = zfs_list_dataset(spa, objid);
return (zfs_list_dataset(spa, objid));
}
int
zfs_bootenv(const char *name)
{
static char poolname[ZFS_MAXNAMELEN], *dsname;
char becount[4];
uint64_t objid;
spa_t *spa;
int len, rv, pages, perpage, currpage;
if (strcmp(name, getenv("zfs_be_root")) != 0) {
if (setenv("zfs_be_root", name, 1) != 0)
return (ENOMEM);
}
SLIST_INIT(&zfs_be_head);
zfs_env_count = 0;
len = strlen(name);
dsname = strchr(name, '/');
if (dsname != NULL) {
len = dsname - name;
dsname++;
} else
dsname = "";
memcpy(poolname, name, len);
poolname[len] = '\0';
spa = spa_find_by_name(poolname);
if (!spa)
return (ENXIO);
rv = zfs_lookup_dataset(spa, dsname, &objid);
if (rv != 0)
return (rv);
rv = zfs_callback_dataset(spa, objid, zfs_belist_add);
/* Calculate and store the number of pages of BEs */
perpage = (ZFS_BE_LAST - ZFS_BE_FIRST + 1);
pages = (zfs_env_count / perpage) + ((zfs_env_count % perpage) > 0 ? 1 : 0);
snprintf(becount, 4, "%d", pages);
if (setenv("zfs_be_pages", becount, 1) != 0)
return (ENOMEM);
/* Roll over the page counter if it has exceeded the maximum */
currpage = strtol(getenv("zfs_be_currpage"), NULL, 10);
if (currpage > pages) {
if (setenv("zfs_be_currpage", "1", 1) != 0)
return (ENOMEM);
}
/* Populate the menu environment variables */
zfs_set_env();
/* Clean up the SLIST of ZFS BEs */
while (!SLIST_EMPTY(&zfs_be_head)) {
zfs_be = SLIST_FIRST(&zfs_be_head);
SLIST_REMOVE_HEAD(&zfs_be_head, entries);
free(zfs_be);
}
return (rv);
}
int
zfs_belist_add(const char *name)
{
/* Add the boot environment to the head of the SLIST */
zfs_be = malloc(sizeof(struct zfs_be_entry));
zfs_be->name = name;
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries);
zfs_env_count++;
return (0);
}
int
zfs_set_env(void)
{
char envname[32], envval[256];
char *beroot, *pagenum;
int rv, page, ctr;
beroot = getenv("zfs_be_root");
if (beroot == NULL) {
return (1);
}
pagenum = getenv("zfs_be_currpage");
if (pagenum != NULL) {
page = strtol(pagenum, NULL, 10);
} else {
page = 1;
}
ctr = 1;
rv = 0;
zfs_env_index = ZFS_BE_FIRST;
SLIST_FOREACH_SAFE(zfs_be, &zfs_be_head, entries, zfs_be_tmp) {
/* Skip to the requested page number */
if (ctr <= ((ZFS_BE_LAST - ZFS_BE_FIRST + 1) * (page - 1))) {
ctr++;
continue;
}
snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index);
snprintf(envval, sizeof(envval), "%s", zfs_be->name);
rv = setenv(envname, envval, 1);
if (rv != 0) {
break;
}
snprintf(envname, sizeof(envname), "bootenvansi_caption[%d]", zfs_env_index);
rv = setenv(envname, envval, 1);
if (rv != 0){
break;
}
snprintf(envname, sizeof(envname), "bootenvmenu_command[%d]", zfs_env_index);
rv = setenv(envname, "set_bootenv", 1);
if (rv != 0){
break;
}
snprintf(envname, sizeof(envname), "bootenv_root[%d]", zfs_env_index);
snprintf(envval, sizeof(envval), "zfs:%s/%s", beroot, zfs_be->name);
rv = setenv(envname, envval, 1);
if (rv != 0){
break;
}
zfs_env_index++;
if (zfs_env_index > ZFS_BE_LAST) {
break;
}
}
for (; zfs_env_index <= ZFS_BE_LAST; zfs_env_index++) {
snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index);
(void)unsetenv(envname);
snprintf(envname, sizeof(envname), "bootenvansi_caption[%d]", zfs_env_index);
(void)unsetenv(envname);
snprintf(envname, sizeof(envname), "bootenvmenu_command[%d]", zfs_env_index);
(void)unsetenv(envname);
snprintf(envname, sizeof(envname), "bootenv_root[%d]", zfs_env_index);
(void)unsetenv(envname);
}
return (rv);
}

View File

@ -1473,7 +1473,7 @@ zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name, uint64
* the directory contents.
*/
static int
mzap_list(const dnode_phys_t *dnode)
mzap_list(const dnode_phys_t *dnode, int (*callback)(const char *))
{
const mzap_phys_t *mz;
const mzap_ent_phys_t *mze;
@ -1492,7 +1492,7 @@ mzap_list(const dnode_phys_t *dnode)
mze = &mz->mz_chunk[i];
if (mze->mze_name[0])
//printf("%-32s 0x%jx\n", mze->mze_name, (uintmax_t)mze->mze_value);
printf("%s\n", mze->mze_name);
callback(mze->mze_name);
}
return (0);
@ -1503,7 +1503,7 @@ mzap_list(const dnode_phys_t *dnode)
* the directory header.
*/
static int
fzap_list(const spa_t *spa, const dnode_phys_t *dnode)
fzap_list(const spa_t *spa, const dnode_phys_t *dnode, int (*callback)(const char *))
{
int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
zap_phys_t zh = *(zap_phys_t *) zap_scratch;
@ -1566,13 +1566,21 @@ fzap_list(const spa_t *spa, const dnode_phys_t *dnode)
value = fzap_leaf_value(&zl, zc);
//printf("%s 0x%jx\n", name, (uintmax_t)value);
printf("%s\n", name);
callback((const char *)name);
}
}
return (0);
}
static int zfs_printf(const char *name)
{
printf("%s\n", name);
return (0);
}
/*
* List a zap directory.
*/
@ -1587,9 +1595,9 @@ zap_list(const spa_t *spa, const dnode_phys_t *dnode)
zap_type = *(uint64_t *) zap_scratch;
if (zap_type == ZBT_MICRO)
return mzap_list(dnode);
return mzap_list(dnode, zfs_printf);
else
return fzap_list(spa, dnode);
return fzap_list(spa, dnode, zfs_printf);
}
static int
@ -1858,6 +1866,48 @@ zfs_list_dataset(const spa_t *spa, uint64_t objnum/*, int pos, char *entry*/)
return (zap_list(spa, &child_dir_zap) != 0);
}
int
zfs_callback_dataset(const spa_t *spa, uint64_t objnum, int (*callback)(const char *name))
{
uint64_t dir_obj, child_dir_zapobj, zap_type;
dnode_phys_t child_dir_zap, dir, dataset;
dsl_dataset_phys_t *ds;
dsl_dir_phys_t *dd;
int err;
err = objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset);
if (err != 0) {
printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
return (err);
}
ds = (dsl_dataset_phys_t *) &dataset.dn_bonus;
dir_obj = ds->ds_dir_obj;
err = objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir);
if (err != 0) {
printf("ZFS: can't find dirobj %ju\n", (uintmax_t)dir_obj);
return (err);
}
dd = (dsl_dir_phys_t *)&dir.dn_bonus;
child_dir_zapobj = dd->dd_child_dir_zapobj;
err = objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_zap);
if (err != 0) {
printf("ZFS: can't find child zap %ju\n", (uintmax_t)dir_obj);
return (err);
}
err = dnode_read(spa, &child_dir_zap, 0, zap_scratch, child_dir_zap.dn_datablkszsec * 512);
if (err != 0)
return (err);
zap_type = *(uint64_t *) zap_scratch;
if (zap_type == ZBT_MICRO)
return mzap_list(&child_dir_zap, callback);
else
return fzap_list(spa, &child_dir_zap, callback);
}
#endif
/*

View File

@ -41,6 +41,8 @@ struct inode;
struct module;
extern struct cdevsw linuxcdevsw;
extern const struct kobj_type linux_cdev_ktype;
extern const struct kobj_type linux_cdev_static_ktype;
struct linux_cdev {
struct kobject kobj;
@ -50,40 +52,11 @@ struct linux_cdev {
const struct file_operations *ops;
};
static inline void
cdev_release(struct kobject *kobj)
{
struct linux_cdev *cdev;
cdev = container_of(kobj, struct linux_cdev, kobj);
if (cdev->cdev)
destroy_dev(cdev->cdev);
kfree(cdev);
}
static inline void
cdev_static_release(struct kobject *kobj)
{
struct linux_cdev *cdev;
cdev = container_of(kobj, struct linux_cdev, kobj);
if (cdev->cdev)
destroy_dev(cdev->cdev);
}
static struct kobj_type cdev_ktype = {
.release = cdev_release,
};
static struct kobj_type cdev_static_ktype = {
.release = cdev_static_release,
};
static inline void
cdev_init(struct linux_cdev *cdev, const struct file_operations *ops)
{
kobject_init(&cdev->kobj, &cdev_static_ktype);
kobject_init(&cdev->kobj, &linux_cdev_static_ktype);
cdev->ops = ops;
}
@ -94,7 +67,7 @@ cdev_alloc(void)
cdev = kzalloc(sizeof(struct linux_cdev), M_WAITOK);
if (cdev)
kobject_init(&cdev->kobj, &cdev_ktype);
kobject_init(&cdev->kobj, &linux_cdev_ktype);
return (cdev);
}
@ -114,6 +87,7 @@ cdev_add(struct linux_cdev *cdev, dev_t dev, unsigned count)
cdev->dev = dev;
cdev->cdev->si_drv1 = cdev;
kobject_get(cdev->kobj.parent);
return (0);
}

View File

@ -73,8 +73,10 @@ struct device {
unsigned int msix_max;
};
extern struct device linux_rootdev;
extern struct kobject class_root;
extern struct device linux_root_device;
extern struct kobject linux_class_root;
extern const struct kobj_type linux_dev_ktype;
extern const struct kobj_type linux_class_ktype;
struct class_attribute {
struct attribute attr;
@ -170,62 +172,14 @@ put_device(struct device *dev)
kobject_put(&dev->kobj);
}
static inline ssize_t
class_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct class_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct class_attribute, attr);
error = -EIO;
if (dattr->show)
error = dattr->show(container_of(kobj, struct class, kobj),
dattr, buf);
return (error);
}
static inline ssize_t
class_store(struct kobject *kobj, struct attribute *attr, const char *buf,
size_t count)
{
struct class_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct class_attribute, attr);
error = -EIO;
if (dattr->store)
error = dattr->store(container_of(kobj, struct class, kobj),
dattr, buf, count);
return (error);
}
static inline void
class_release(struct kobject *kobj)
{
struct class *class;
class = container_of(kobj, struct class, kobj);
if (class->class_release)
class->class_release(class);
}
static struct sysfs_ops class_sysfs = {
.show = class_show,
.store = class_store,
};
static struct kobj_type class_ktype = {
.release = class_release,
.sysfs_ops = &class_sysfs
};
static inline int
class_register(struct class *class)
{
class->bsdclass = devclass_create(class->name);
kobject_init(&class->kobj, &class_ktype);
kobject_init(&class->kobj, &linux_class_ktype);
kobject_set_name(&class->kobj, class->name);
kobject_add(&class->kobj, &class_root, class->name);
kobject_add(&class->kobj, &linux_class_root, class->name);
return (0);
}
@ -237,54 +191,6 @@ class_unregister(struct class *class)
kobject_put(&class->kobj);
}
static inline void
device_release(struct kobject *kobj)
{
struct device *dev;
dev = container_of(kobj, struct device, kobj);
/* This is the precedence defined by linux. */
if (dev->release)
dev->release(dev);
else if (dev->class && dev->class->dev_release)
dev->class->dev_release(dev);
}
static inline ssize_t
dev_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct device_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct device_attribute, attr);
error = -EIO;
if (dattr->show)
error = dattr->show(container_of(kobj, struct device, kobj),
dattr, buf);
return (error);
}
static inline ssize_t
dev_store(struct kobject *kobj, struct attribute *attr, const char *buf,
size_t count)
{
struct device_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct device_attribute, attr);
error = -EIO;
if (dattr->store)
error = dattr->store(container_of(kobj, struct device, kobj),
dattr, buf, count);
return (error);
}
static struct sysfs_ops dev_sysfs = { .show = dev_show, .store = dev_store, };
static struct kobj_type dev_ktype = {
.release = device_release,
.sysfs_ops = &dev_sysfs
};
/*
* Devices are registered and created for exporting to sysfs. create
* implies register and register assumes the device fields have been
@ -311,7 +217,7 @@ device_register(struct device *dev)
device_set_softc(bsddev, dev);
}
dev->bsddev = bsddev;
kobject_init(&dev->kobj, &dev_ktype);
kobject_init(&dev->kobj, &linux_dev_ktype);
kobject_add(&dev->kobj, &dev->class->kobj, dev_name(dev));
return (0);
@ -346,7 +252,7 @@ device_destroy(struct class *class, dev_t devt)
}
static inline void
class_kfree(struct class *class)
linux_class_kfree(struct class *class)
{
kfree(class);
@ -361,7 +267,7 @@ class_create(struct module *owner, const char *name)
class = kzalloc(sizeof(*class), M_WAITOK);
class->owner = owner;
class->name= name;
class->class_release = class_kfree;
class->class_release = linux_class_kfree;
error = class_register(class);
if (error) {
kfree(class);
@ -414,7 +320,8 @@ class_remove_file(struct class *class, const struct class_attribute *attr)
sysfs_remove_file(&class->kobj, &attr->attr);
}
static inline int dev_to_node(struct device *dev)
static inline int
dev_to_node(struct device *dev)
{
return -1;
}

View File

@ -101,10 +101,11 @@ fd_install(unsigned int fd, struct linux_file *filp)
if (fget_unlocked(curthread->td_proc->p_fd, fd,
cap_rights_init(&rights), &file, NULL) != 0) {
file = NULL;
filp->_file = NULL;
} else {
filp->_file = file;
finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops);
}
filp->_file = file;
finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops);
/* drop the extra reference */
fput(filp);

View File

@ -46,13 +46,13 @@ struct kobj_type {
struct attribute **default_attrs;
};
extern struct kobj_type kfree_type;
extern const struct kobj_type linux_kfree_type;
struct kobject {
struct kobject *parent;
char *name;
struct kref kref;
struct kobj_type *ktype;
const struct kobj_type *ktype;
struct list_head entry;
struct sysctl_oid *oidp;
};
@ -74,7 +74,7 @@ struct kobj_attribute {
};
static inline void
kobject_init(struct kobject *kobj, struct kobj_type *ktype)
kobject_init(struct kobject *kobj, const struct kobj_type *ktype)
{
kref_init(&kobj->kref);
@ -83,15 +83,14 @@ kobject_init(struct kobject *kobj, struct kobj_type *ktype)
kobj->oidp = NULL;
}
static inline void kobject_put(struct kobject *kobj);
void kobject_release(struct kref *kref);
void linux_kobject_release(struct kref *kref);
static inline void
kobject_put(struct kobject *kobj)
{
if (kobj)
kref_put(&kobj->kref, kobject_release);
kref_put(&kobj->kref, linux_kobject_release);
}
static inline struct kobject *
@ -115,7 +114,7 @@ kobject_create(void)
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (kobj == NULL)
return (NULL);
kobject_init(kobj, &kfree_type);
kobject_init(kobj, &linux_kfree_type);
return (kobj);
}
@ -135,7 +134,6 @@ kobject_create_and_add(const char *name, struct kobject *parent)
return (NULL);
}
static inline char *
kobject_name(const struct kobject *kobj)
{
@ -144,7 +142,7 @@ kobject_name(const struct kobject *kobj)
}
int kobject_set_name(struct kobject *kobj, const char *fmt, ...);
int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
int kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype,
struct kobject *parent, const char *fmt, ...);
#endif /* _LINUX_KOBJECT_H_ */

View File

@ -46,13 +46,13 @@ struct miscdevice {
umode_t mode;
};
extern struct class miscclass;
extern struct class linux_class_misc;
static inline int
misc_register(struct miscdevice *misc)
{
misc->this_device = device_create(&miscclass, &linux_rootdev, 0, misc,
misc->name);
misc->this_device = device_create(&linux_class_misc,
&linux_root_device, 0, misc, misc->name);
misc->cdev = cdev_alloc();
if (misc->cdev == NULL)
return -ENOMEM;
@ -67,7 +67,7 @@ misc_register(struct miscdevice *misc)
static inline int
misc_deregister(struct miscdevice *misc)
{
device_destroy(&miscclass, misc->this_device->devt);
device_destroy(&linux_class_misc, misc->this_device->devt);
cdev_del(misc->cdev);
return (0);

View File

@ -77,9 +77,9 @@ MALLOC_DEFINE(M_KMALLOC, "linux", "Linux kmalloc compat");
#undef cdev
#define RB_ROOT(head) (head)->rbh_root
struct kobject class_root;
struct device linux_rootdev;
struct class miscclass;
struct kobject linux_class_root;
struct device linux_root_device;
struct class linux_class_misc;
struct list_head pci_drivers;
struct list_head pci_devices;
struct net init_net;
@ -151,13 +151,13 @@ kobject_set_name(struct kobject *kobj, const char *fmt, ...)
return (error);
}
static inline int
static int
kobject_add_complete(struct kobject *kobj, struct kobject *parent)
{
struct kobj_type *t;
const struct kobj_type *t;
int error;
kobj->parent = kobject_get(parent);
kobj->parent = parent;
error = sysfs_create_dir(kobj);
if (error == 0 && kobj->ktype && kobj->ktype->default_attrs) {
struct attribute **attr;
@ -191,16 +191,13 @@ kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...)
}
void
kobject_release(struct kref *kref)
linux_kobject_release(struct kref *kref)
{
struct kobject *kobj;
char *name;
kobj = container_of(kref, struct kobject, kref);
sysfs_remove_dir(kobj);
if (kobj->parent)
kobject_put(kobj->parent);
kobj->parent = NULL;
name = kobj->name;
if (kobj->ktype && kobj->ktype->release)
kobj->ktype->release(kobj);
@ -208,28 +205,131 @@ kobject_release(struct kref *kref)
}
static void
kobject_kfree(struct kobject *kobj)
linux_kobject_kfree(struct kobject *kobj)
{
kfree(kobj);
}
static void
kobject_kfree_name(struct kobject *kobj)
linux_kobject_kfree_name(struct kobject *kobj)
{
if (kobj) {
kfree(kobj->name);
}
}
struct kobj_type kfree_type = { .release = kobject_kfree };
const struct kobj_type linux_kfree_type = {
.release = linux_kobject_kfree
};
static void
dev_release(struct device *dev)
linux_device_release(struct device *dev)
{
pr_debug("dev_release: %s\n", dev_name(dev));
pr_debug("linux_device_release: %s\n", dev_name(dev));
kfree(dev);
}
static ssize_t
linux_class_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct class_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct class_attribute, attr);
error = -EIO;
if (dattr->show)
error = dattr->show(container_of(kobj, struct class, kobj),
dattr, buf);
return (error);
}
static ssize_t
linux_class_store(struct kobject *kobj, struct attribute *attr, const char *buf,
size_t count)
{
struct class_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct class_attribute, attr);
error = -EIO;
if (dattr->store)
error = dattr->store(container_of(kobj, struct class, kobj),
dattr, buf, count);
return (error);
}
static void
linux_class_release(struct kobject *kobj)
{
struct class *class;
class = container_of(kobj, struct class, kobj);
if (class->class_release)
class->class_release(class);
}
static const struct sysfs_ops linux_class_sysfs = {
.show = linux_class_show,
.store = linux_class_store,
};
const struct kobj_type linux_class_ktype = {
.release = linux_class_release,
.sysfs_ops = &linux_class_sysfs
};
static void
linux_dev_release(struct kobject *kobj)
{
struct device *dev;
dev = container_of(kobj, struct device, kobj);
/* This is the precedence defined by linux. */
if (dev->release)
dev->release(dev);
else if (dev->class && dev->class->dev_release)
dev->class->dev_release(dev);
}
static ssize_t
linux_dev_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct device_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct device_attribute, attr);
error = -EIO;
if (dattr->show)
error = dattr->show(container_of(kobj, struct device, kobj),
dattr, buf);
return (error);
}
static ssize_t
linux_dev_store(struct kobject *kobj, struct attribute *attr, const char *buf,
size_t count)
{
struct device_attribute *dattr;
ssize_t error;
dattr = container_of(attr, struct device_attribute, attr);
error = -EIO;
if (dattr->store)
error = dattr->store(container_of(kobj, struct device, kobj),
dattr, buf, count);
return (error);
}
static const struct sysfs_ops linux_dev_sysfs = {
.show = linux_dev_show,
.store = linux_dev_store,
};
const struct kobj_type linux_dev_ktype = {
.release = linux_dev_release,
.sysfs_ops = &linux_dev_sysfs
};
struct device *
device_create(struct class *class, struct device *parent, dev_t devt,
void *drvdata, const char *fmt, ...)
@ -242,7 +342,7 @@ device_create(struct class *class, struct device *parent, dev_t devt,
dev->class = class;
dev->devt = devt;
dev->driver_data = drvdata;
dev->release = dev_release;
dev->release = linux_device_release;
va_start(args, fmt);
kobject_set_name_vargs(&dev->kobj, fmt, args);
va_end(args);
@ -252,7 +352,7 @@ device_create(struct class *class, struct device *parent, dev_t devt,
}
int
kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype,
struct kobject *parent, const char *fmt, ...)
{
va_list args;
@ -1001,6 +1101,41 @@ destroy_workqueue(struct workqueue_struct *wq)
kfree(wq);
}
static void
linux_cdev_release(struct kobject *kobj)
{
struct linux_cdev *cdev;
struct kobject *parent;
cdev = container_of(kobj, struct linux_cdev, kobj);
parent = kobj->parent;
if (cdev->cdev)
destroy_dev(cdev->cdev);
kfree(cdev);
kobject_put(parent);
}
static void
linux_cdev_static_release(struct kobject *kobj)
{
struct linux_cdev *cdev;
struct kobject *parent;
cdev = container_of(kobj, struct linux_cdev, kobj);
parent = kobj->parent;
if (cdev->cdev)
destroy_dev(cdev->cdev);
kobject_put(parent);
}
const struct kobj_type linux_cdev_ktype = {
.release = linux_cdev_release,
};
const struct kobj_type linux_cdev_static_ktype = {
.release = linux_cdev_static_release,
};
static void
linux_compat_init(void *arg)
{
@ -1009,18 +1144,18 @@ linux_compat_init(void *arg)
rootoid = SYSCTL_ADD_ROOT_NODE(NULL,
OID_AUTO, "sys", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "sys");
kobject_init(&class_root, &class_ktype);
kobject_set_name(&class_root, "class");
class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid),
kobject_init(&linux_class_root, &linux_class_ktype);
kobject_set_name(&linux_class_root, "class");
linux_class_root.oidp = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(rootoid),
OID_AUTO, "class", CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, "class");
kobject_init(&linux_rootdev.kobj, &dev_ktype);
kobject_set_name(&linux_rootdev.kobj, "device");
linux_rootdev.kobj.oidp = SYSCTL_ADD_NODE(NULL,
kobject_init(&linux_root_device.kobj, &linux_dev_ktype);
kobject_set_name(&linux_root_device.kobj, "device");
linux_root_device.kobj.oidp = SYSCTL_ADD_NODE(NULL,
SYSCTL_CHILDREN(rootoid), OID_AUTO, "device", CTLFLAG_RD, NULL,
"device");
linux_rootdev.bsddev = root_bus;
miscclass.name = "misc";
class_register(&miscclass);
linux_root_device.bsddev = root_bus;
linux_class_misc.name = "misc";
class_register(&linux_class_misc);
INIT_LIST_HEAD(&pci_drivers);
INIT_LIST_HEAD(&pci_devices);
spin_lock_init(&pci_lock);
@ -1033,9 +1168,9 @@ SYSINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_init, NULL);
static void
linux_compat_uninit(void *arg)
{
kobject_kfree_name(&class_root);
kobject_kfree_name(&linux_rootdev.kobj);
kobject_kfree_name(&miscclass.kobj);
linux_kobject_kfree_name(&linux_class_root);
linux_kobject_kfree_name(&linux_root_device.kobj);
linux_kobject_kfree_name(&linux_class_misc.kobj);
}
SYSUNINIT(linux_compat, SI_SUB_DRIVERS, SI_ORDER_SECOND, linux_compat_uninit, NULL);

View File

@ -119,16 +119,16 @@ linux_pci_attach(device_t dev)
pdrv = linux_pci_find(dev, &id);
pdev = device_get_softc(dev);
pdev->dev.parent = &linux_rootdev;
pdev->dev.parent = &linux_root_device;
pdev->dev.bsddev = dev;
INIT_LIST_HEAD(&pdev->dev.irqents);
pdev->device = id->device;
pdev->vendor = id->vendor;
pdev->dev.dma_mask = &pdev->dma_mask;
pdev->pdrv = pdrv;
kobject_init(&pdev->dev.kobj, &dev_ktype);
kobject_init(&pdev->dev.kobj, &linux_dev_ktype);
kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev));
kobject_add(&pdev->dev.kobj, &linux_rootdev.kobj,
kobject_add(&pdev->dev.kobj, &linux_root_device.kobj,
kobject_name(&pdev->dev.kobj));
rle = _pci_get_rle(pdev, SYS_RES_IRQ, 0);
if (rle)

View File

@ -97,7 +97,10 @@ then
fi
touch version
v=`cat version` u=${USER:-root} d=`pwd` h=${HOSTNAME:-`hostname`}
v=`cat version`
u=${USER:-root}
d=`pwd`
h=${HOSTNAME:-`hostname`}
if [ -n "$SOURCE_DATE_EPOCH" ]; then
if ! t=`date -r $SOURCE_DATE_EPOCH 2>/dev/null`; then
echo "Invalid SOURCE_DATE_EPOCH" >&2

View File

@ -53,6 +53,7 @@ struct sha1_ctxt {
} m;
u_int8_t count;
};
typedef struct sha1_ctxt SHA1_CTX;
#ifdef _KERNEL
extern void sha1_init(struct sha1_ctxt *);
@ -61,7 +62,6 @@ extern void sha1_loop(struct sha1_ctxt *, const u_int8_t *, size_t);
extern void sha1_result(struct sha1_ctxt *, caddr_t);
/* compatibilty with other SHA1 source codes */
typedef struct sha1_ctxt SHA1_CTX;
#define SHA1Init(x) sha1_init((x))
#define SHA1Update(x, y, z) sha1_loop((x), (y), (z))
#define SHA1Final(x, y) sha1_result((y), (x))

View File

@ -215,7 +215,7 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e)
struct tom_data *td = sc->tom_softc;
struct toedev *tod = &td->tod;
struct sockaddr_in sin = {0};
uint8_t dmac[ETHER_ADDR_LEN];
uint8_t dmac[ETHER_HDR_LEN];
uint16_t vtag = EVL_VLID_MASK;
int rc;

View File

@ -233,7 +233,7 @@ resolve_entry(struct adapter *sc, struct l2t_entry *e)
struct sockaddr_in sin = {0};
struct sockaddr_in6 sin6 = {0};
struct sockaddr *sa;
uint8_t dmac[ETHER_ADDR_LEN];
uint8_t dmac[ETHER_HDR_LEN];
uint16_t vtag = VLAN_NONE;
int rc;

View File

@ -698,7 +698,7 @@ enum mlx5e_link_mode {
MLX5E_56GBASE_R4 = 8,
MLX5E_10GBASE_CR = 12,
MLX5E_10GBASE_SR = 13,
MLX5E_10GBASE_ER = 14,
MLX5E_10GBASE_LR = 14,
MLX5E_40GBASE_SR4 = 15,
MLX5E_40GBASE_LR4 = 16,
MLX5E_100GBASE_CR4 = 20,
@ -787,5 +787,6 @@ void mlx5e_create_stats(struct sysctl_ctx_list *,
struct sysctl_oid_list *, const char *,
const char **, unsigned, u64 *);
void mlx5e_send_nop(struct mlx5e_sq *, u32, bool);
int mlx5e_refresh_channel_params(struct mlx5e_priv *);
#endif /* _MLX5_EN_H_ */

View File

@ -69,12 +69,49 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
} else {
error = 0;
}
/* check if device is gone */
if (priv->gone) {
error = ENXIO;
goto done;
}
/* import RX coal time */
if (priv->params_ethtool.rx_coalesce_usecs < 1)
priv->params_ethtool.rx_coalesce_usecs = 0;
else if (priv->params_ethtool.rx_coalesce_usecs >
MLX5E_FLD_MAX(cqc, cq_period)) {
priv->params_ethtool.rx_coalesce_usecs =
MLX5E_FLD_MAX(cqc, cq_period);
}
priv->params.rx_cq_moderation_usec = priv->params_ethtool.rx_coalesce_usecs;
/* import RX coal pkts */
if (priv->params_ethtool.rx_coalesce_pkts < 1)
priv->params_ethtool.rx_coalesce_pkts = 0;
else if (priv->params_ethtool.rx_coalesce_pkts >
MLX5E_FLD_MAX(cqc, cq_max_count)) {
priv->params_ethtool.rx_coalesce_pkts =
MLX5E_FLD_MAX(cqc, cq_max_count);
}
priv->params.rx_cq_moderation_pkts = priv->params_ethtool.rx_coalesce_pkts;
/* import TX coal time */
if (priv->params_ethtool.tx_coalesce_usecs < 1)
priv->params_ethtool.tx_coalesce_usecs = 0;
else if (priv->params_ethtool.tx_coalesce_usecs >
MLX5E_FLD_MAX(cqc, cq_period)) {
priv->params_ethtool.tx_coalesce_usecs =
MLX5E_FLD_MAX(cqc, cq_period);
}
priv->params.tx_cq_moderation_usec = priv->params_ethtool.tx_coalesce_usecs;
/* import TX coal pkts */
if (priv->params_ethtool.tx_coalesce_pkts < 1)
priv->params_ethtool.tx_coalesce_pkts = 0;
else if (priv->params_ethtool.tx_coalesce_pkts >
MLX5E_FLD_MAX(cqc, cq_max_count)) {
priv->params_ethtool.tx_coalesce_pkts = MLX5E_FLD_MAX(cqc, cq_max_count);
}
priv->params.tx_cq_moderation_pkts = priv->params_ethtool.tx_coalesce_pkts;
if (&priv->params_ethtool.arg[arg2] == &priv->params_ethtool.rx_pauseframe_control ||
&priv->params_ethtool.arg[arg2] == &priv->params_ethtool.tx_pauseframe_control) {
@ -92,9 +129,19 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
}
was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
if (was_opened)
mlx5e_close_locked(priv->ifp);
if (was_opened) {
u64 *xarg = priv->params_ethtool.arg + arg2;
if (xarg == &priv->params_ethtool.tx_coalesce_pkts ||
xarg == &priv->params_ethtool.rx_coalesce_pkts ||
xarg == &priv->params_ethtool.tx_coalesce_usecs ||
xarg == &priv->params_ethtool.rx_coalesce_usecs) {
/* avoid downing and upping the network interface */
error = mlx5e_refresh_channel_params(priv);
goto done;
}
mlx5e_close_locked(priv->ifp);
}
/* import TX queue size */
if (priv->params_ethtool.tx_queue_size <
(1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
@ -145,45 +192,6 @@ mlx5e_ethtool_handler(SYSCTL_HANDLER_ARGS)
priv->params_ethtool.tx_coalesce_mode = 1;
priv->params.tx_cq_moderation_mode = priv->params_ethtool.tx_coalesce_mode;
/* import RX coal time */
if (priv->params_ethtool.rx_coalesce_usecs < 1)
priv->params_ethtool.rx_coalesce_usecs = 0;
else if (priv->params_ethtool.rx_coalesce_usecs >
MLX5E_FLD_MAX(cqc, cq_period)) {
priv->params_ethtool.rx_coalesce_usecs =
MLX5E_FLD_MAX(cqc, cq_period);
}
priv->params.rx_cq_moderation_usec = priv->params_ethtool.rx_coalesce_usecs;
/* import RX coal pkts */
if (priv->params_ethtool.rx_coalesce_pkts < 1)
priv->params_ethtool.rx_coalesce_pkts = 0;
else if (priv->params_ethtool.rx_coalesce_pkts >
MLX5E_FLD_MAX(cqc, cq_max_count)) {
priv->params_ethtool.rx_coalesce_pkts =
MLX5E_FLD_MAX(cqc, cq_max_count);
}
priv->params.rx_cq_moderation_pkts = priv->params_ethtool.rx_coalesce_pkts;
/* import TX coal time */
if (priv->params_ethtool.tx_coalesce_usecs < 1)
priv->params_ethtool.tx_coalesce_usecs = 0;
else if (priv->params_ethtool.tx_coalesce_usecs >
MLX5E_FLD_MAX(cqc, cq_period)) {
priv->params_ethtool.tx_coalesce_usecs =
MLX5E_FLD_MAX(cqc, cq_period);
}
priv->params.tx_cq_moderation_usec = priv->params_ethtool.tx_coalesce_usecs;
/* import TX coal pkts */
if (priv->params_ethtool.tx_coalesce_pkts < 1)
priv->params_ethtool.tx_coalesce_pkts = 0;
else if (priv->params_ethtool.tx_coalesce_pkts >
MLX5E_FLD_MAX(cqc, cq_max_count)) {
priv->params_ethtool.tx_coalesce_pkts = MLX5E_FLD_MAX(cqc, cq_max_count);
}
priv->params.tx_cq_moderation_pkts = priv->params_ethtool.tx_coalesce_pkts;
/* we always agree to turn off HW LRO - but not always to turn on */
if (priv->params_ethtool.hw_lro) {
if (priv->params_ethtool.hw_lro != 1) {

View File

@ -106,8 +106,8 @@ static const struct {
.subtype = IFM_10G_SR,
.baudrate = IF_Gbps(10ULL),
},
[MLX5E_10GBASE_ER] = {
.subtype = IFM_10G_ER,
[MLX5E_10GBASE_LR] = {
.subtype = IFM_10G_LR,
.baudrate = IF_Gbps(10ULL),
},
[MLX5E_40GBASE_SR4] = {
@ -1711,6 +1711,62 @@ mlx5e_close_channels(struct mlx5e_priv *priv)
free(ptr, M_MLX5EN);
}
static int
mlx5e_refresh_sq_params(struct mlx5e_priv *priv, struct mlx5e_sq *sq)
{
return (mlx5_core_modify_cq_moderation(priv->mdev, &sq->cq.mcq,
priv->params.tx_cq_moderation_usec,
priv->params.tx_cq_moderation_pkts));
}
static int
mlx5e_refresh_rq_params(struct mlx5e_priv *priv, struct mlx5e_rq *rq)
{
return (mlx5_core_modify_cq_moderation(priv->mdev, &rq->cq.mcq,
priv->params.rx_cq_moderation_usec,
priv->params.rx_cq_moderation_pkts));
}
static int
mlx5e_refresh_channel_params_sub(struct mlx5e_priv *priv, struct mlx5e_channel *c)
{
int err;
int i;
if (c == NULL)
return (EINVAL);
err = mlx5e_refresh_rq_params(priv, &c->rq);
if (err)
goto done;
for (i = 0; i != c->num_tc; i++) {
err = mlx5e_refresh_sq_params(priv, &c->sq[i]);
if (err)
goto done;
}
done:
return (err);
}
int
mlx5e_refresh_channel_params(struct mlx5e_priv *priv)
{
int i;
if (priv->channel == NULL)
return (EINVAL);
for (i = 0; i < priv->params.num_channels; i++) {
int err;
err = mlx5e_refresh_channel_params_sub(priv, priv->channel[i]);
if (err)
return (err);
}
return (0);
}
static int
mlx5e_open_tis(struct mlx5e_priv *priv, int tc)
{
@ -2298,6 +2354,7 @@ mlx5e_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
int size_read = 0;
int module_num;
int max_mtu;
uint8_t read_addr;
priv = ifp->if_softc;
@ -2484,11 +2541,21 @@ mlx5e_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
/*
* Note that we ignore i2c.addr here. The driver hardcodes
* the address to 0x50, while standard expects it to be 0xA0.
* Currently 0XA0 and 0xA2 are the only addresses permitted.
* The internal conversion is as follows:
*/
if (i2c.dev_addr == 0xA0)
read_addr = MLX5E_I2C_ADDR_LOW;
else if (i2c.dev_addr == 0xA2)
read_addr = MLX5E_I2C_ADDR_HIGH;
else {
if_printf(ifp, "Query eeprom failed, "
"Invalid Address: %X\n", i2c.dev_addr);
error = EINVAL;
goto err_i2c;
}
error = mlx5_query_eeprom(priv->mdev,
MLX5E_I2C_ADDR_LOW, MLX5E_EEPROM_LOW_PAGE,
read_addr, MLX5E_EEPROM_LOW_PAGE,
(uint32_t)i2c.offset, (uint32_t)i2c.len, module_num,
(uint32_t *)i2c.data, &size_read);
if (error) {
@ -2499,7 +2566,7 @@ mlx5e_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (i2c.len > MLX5_EEPROM_MAX_BYTES) {
error = mlx5_query_eeprom(priv->mdev,
MLX5E_I2C_ADDR_LOW, MLX5E_EEPROM_LOW_PAGE,
read_addr, MLX5E_EEPROM_LOW_PAGE,
(uint32_t)(i2c.offset + size_read),
(uint32_t)(i2c.len - size_read), module_num,
(uint32_t *)(i2c.data + size_read), &size_read);

View File

@ -175,6 +175,7 @@ static const STRUCT_USB_HOST_ID axe_devs[] = {
AXE_DEV(PLANEX3, GU1000T, AXE_FLAG_178),
AXE_DEV(SITECOM, LN029, 0),
AXE_DEV(SITECOMEU, LN028, AXE_FLAG_178),
AXE_DEV(SITECOMEU, LN031, AXE_FLAG_178),
AXE_DEV(SYSTEMTALKS, SGCX2UL, 0),
#undef AXE_DEV
};

View File

@ -4203,6 +4203,7 @@ product SITECOMEU RTL8188CU_1 0x0052 RTL8188CU
product SITECOMEU RTL8188CU_2 0x005c RTL8188CU
product SITECOMEU RTL8192CU 0x0061 RTL8192CU
product SITECOMEU LN032 0x0072 LN-032
product SITECOMEU LN031 0x0056 LN-031
product SITECOMEU LN028 0x061c LN-028
product SITECOMEU WL113 0x9071 WL-113
product SITECOMEU ZD1211B 0x9075 ZD1211B

View File

@ -568,14 +568,16 @@ static int
null_remove(struct vop_remove_args *ap)
{
int retval, vreleit;
struct vnode *lvp;
struct vnode *lvp, *vp;
if (vrefcnt(ap->a_vp) > 1) {
lvp = NULLVPTOLOWERVP(ap->a_vp);
vp = ap->a_vp;
if (vrefcnt(vp) > 1) {
lvp = NULLVPTOLOWERVP(vp);
VREF(lvp);
vreleit = 1;
} else
vreleit = 0;
VTONULL(vp)->null_flags |= NULLV_DROP;
retval = null_bypass(&ap->a_gen);
if (vreleit != 0)
vrele(lvp);

View File

@ -1066,7 +1066,7 @@ fork_return(struct thread *td, struct trapframe *frame)
cv_broadcast(&p->p_dbgwait);
}
PROC_UNLOCK(p);
} else if (p->p_flag & P_TRACED) {
} else if (p->p_flag & P_TRACED || td->td_dbgflags & TDB_BORN) {
/*
* This is the start of a new thread in a traced
* process. Report a system call exit event.
@ -1074,9 +1074,10 @@ fork_return(struct thread *td, struct trapframe *frame)
PROC_LOCK(p);
td->td_dbgflags |= TDB_SCX;
_STOPEVENT(p, S_SCX, td->td_dbg_sc_code);
if ((p->p_stops & S_PT_SCX) != 0)
if ((p->p_stops & S_PT_SCX) != 0 ||
(td->td_dbgflags & TDB_BORN) != 0)
ptracestop(td, SIGTRAP);
td->td_dbgflags &= ~TDB_SCX;
td->td_dbgflags &= ~(TDB_SCX | TDB_BORN);
PROC_UNLOCK(p);
}

View File

@ -55,9 +55,6 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <machine/cpu.h>
#ifdef __sparc64__
#include <machine/ktr.h>
#endif
#ifdef DDB
#include <ddb/ddb.h>

View File

@ -2501,7 +2501,12 @@ ptracestop(struct thread *td, int sig)
td->td_tid, p->p_pid, td->td_dbgflags, sig);
PROC_SLOCK(p);
while ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_XSIG)) {
if (p->p_flag & P_SINGLE_EXIT) {
if (p->p_flag & P_SINGLE_EXIT &&
!(td->td_dbgflags & TDB_EXIT)) {
/*
* Ignore ptrace stops except for thread exit
* events when the process exits.
*/
td->td_dbgflags &= ~TDB_XSIG;
PROC_SUNLOCK(p);
return (sig);

View File

@ -253,6 +253,8 @@ thread_create(struct thread *td, struct rtprio *rtp,
thread_unlock(td);
if (P_SHOULDSTOP(p))
newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK;
if (p->p_flag2 & P2_LWP_EVENTS)
newtd->td_dbgflags |= TDB_BORN;
/*
* Copy the existing thread VM policy into the new thread.
@ -322,29 +324,54 @@ kern_thr_exit(struct thread *td)
p = td->td_proc;
rw_wlock(&tidhash_lock);
/*
* If all of the threads in a process call this routine to
* exit (e.g. all threads call pthread_exit()), exactly one
* thread should return to the caller to terminate the process
* instead of the thread.
*
* Checking p_numthreads alone is not sufficient since threads
* might be committed to terminating while the PROC_LOCK is
* dropped in either ptracestop() or while removing this thread
* from the tidhash. Instead, the p_pendingexits field holds
* the count of threads in either of those states and a thread
* is considered the "last" thread if all of the other threads
* in a process are already terminating.
*/
PROC_LOCK(p);
if (p->p_numthreads != 1) {
racct_sub(p, RACCT_NTHR, 1);
LIST_REMOVE(td, td_hash);
rw_wunlock(&tidhash_lock);
tdsigcleanup(td);
umtx_thread_exit(td);
PROC_SLOCK(p);
thread_stopped(p);
thread_exit();
/* NOTREACHED */
if (p->p_numthreads == p->p_pendingexits + 1) {
/*
* Ignore attempts to shut down last thread in the
* proc. This will actually call _exit(2) in the
* usermode trampoline when it returns.
*/
PROC_UNLOCK(p);
return (0);
}
/*
* Ignore attempts to shut down last thread in the proc. This
* will actually call _exit(2) in the usermode trampoline when
* it returns.
*/
p->p_pendingexits++;
td->td_dbgflags |= TDB_EXIT;
if (p->p_flag & P_TRACED && p->p_flag2 & P2_LWP_EVENTS)
ptracestop(td, SIGTRAP);
PROC_UNLOCK(p);
rw_wunlock(&tidhash_lock);
return (0);
tidhash_remove(td);
PROC_LOCK(p);
p->p_pendingexits--;
/*
* The check above should prevent all other threads from this
* process from exiting while the PROC_LOCK is dropped, so
* there must be at least one other thread other than the
* current thread.
*/
KASSERT(p->p_numthreads > 1, ("too few threads"));
racct_sub(p, RACCT_NTHR, 1);
tdsigcleanup(td);
umtx_thread_exit(td);
PROC_SLOCK(p);
thread_stopped(p);
thread_exit();
/* NOTREACHED */
}
int

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sched.h>
#include <sys/sleepqueue.h>
#include <sys/selinfo.h>
#include <sys/syscallsubr.h>
#include <sys/sysent.h>
#include <sys/turnstile.h>
#include <sys/ktr.h>
@ -942,7 +943,6 @@ thread_suspend_check(int return_instead)
*/
if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
PROC_UNLOCK(p);
tidhash_remove(td);
/*
* Allow Linux emulation layer to do some work
@ -950,13 +950,8 @@ thread_suspend_check(int return_instead)
*/
if (__predict_false(p->p_sysent->sv_thread_detach != NULL))
(p->p_sysent->sv_thread_detach)(td);
PROC_LOCK(p);
tdsigcleanup(td);
umtx_thread_exit(td);
PROC_SLOCK(p);
thread_stopped(p);
thread_exit();
kern_thr_exit(td);
panic("stopped thread did not exit");
}
PROC_SLOCK(p);

View File

@ -710,6 +710,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
case PT_TO_SCX:
case PT_SYSCALL:
case PT_FOLLOW_FORK:
case PT_LWP_EVENTS:
case PT_DETACH:
sx_xlock(&proctree_lock);
proctree_locked = 1;
@ -948,6 +949,16 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
p->p_flag &= ~P_FOLLOWFORK;
break;
case PT_LWP_EVENTS:
CTR3(KTR_PTRACE, "PT_LWP_EVENTS: pid %d %s -> %s", p->p_pid,
p->p_flag2 & P2_LWP_EVENTS ? "enabled" : "disabled",
data ? "enabled" : "disabled");
if (data)
p->p_flag2 |= P2_LWP_EVENTS;
else
p->p_flag2 &= ~P2_LWP_EVENTS;
break;
case PT_STEP:
case PT_CONTINUE:
case PT_TO_SCE:
@ -1252,6 +1263,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
}
if (td2->td_dbgflags & TDB_CHILD)
pl->pl_flags |= PL_FLAG_CHILD;
if (td2->td_dbgflags & TDB_BORN)
pl->pl_flags |= PL_FLAG_BORN;
if (td2->td_dbgflags & TDB_EXIT)
pl->pl_flags |= PL_FLAG_EXITED;
pl->pl_sigmask = td2->td_sigmask;
pl->pl_siglist = td2->td_siglist;
strcpy(pl->pl_tdname, td2->td_name);

View File

@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/bpf.h>
#include <net/bpf_buffer.h>
#ifdef BPF_JITTER
@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <net/bpf_zerocopy.h>
#include <net/bpfdesc.h>
#include <net/route.h>
#include <net/vnet.h>
#include <netinet/in.h>
@ -164,7 +166,7 @@ static void bpf_detachd(struct bpf_d *);
static void bpf_detachd_locked(struct bpf_d *);
static void bpf_freed(struct bpf_d *);
static int bpf_movein(struct uio *, int, struct ifnet *, struct mbuf **,
struct sockaddr *, int *, struct bpf_insn *);
struct sockaddr *, int *, struct bpf_d *);
static int bpf_setif(struct bpf_d *, struct ifreq *);
static void bpf_timed_out(void *);
static __inline void
@ -454,7 +456,7 @@ bpf_ioctl_setzbuf(struct thread *td, struct bpf_d *d, struct bpf_zbuf *bz)
*/
static int
bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp,
struct sockaddr *sockp, int *hdrlen, struct bpf_insn *wfilter)
struct sockaddr *sockp, int *hdrlen, struct bpf_d *d)
{
const struct ieee80211_bpf_params *p;
struct ether_header *eh;
@ -549,7 +551,7 @@ bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp,
if (error)
goto bad;
slen = bpf_filter(wfilter, mtod(m, u_char *), len, len);
slen = bpf_filter(d->bd_wfilter, mtod(m, u_char *), len, len);
if (slen == 0) {
error = EPERM;
goto bad;
@ -566,6 +568,10 @@ bpf_movein(struct uio *uio, int linktype, struct ifnet *ifp, struct mbuf **mp,
else
m->m_flags |= M_MCAST;
}
if (d->bd_hdrcmplt == 0) {
memcpy(eh->ether_shost, IF_LLADDR(ifp),
sizeof(eh->ether_shost));
}
break;
}
@ -1088,6 +1094,7 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
struct ifnet *ifp;
struct mbuf *m, *mc;
struct sockaddr dst;
struct route ro;
int error, hlen;
error = devfs_get_cdevpriv((void **)&d);
@ -1119,7 +1126,7 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
hlen = 0;
/* XXX: bpf_movein() can sleep */
error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, ifp,
&m, &dst, &hlen, d->bd_wfilter);
&m, &dst, &hlen, d);
if (error) {
d->bd_wdcount++;
return (error);
@ -1151,7 +1158,14 @@ bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
BPFD_UNLOCK(d);
#endif
error = (*ifp->if_output)(ifp, m, &dst, NULL);
bzero(&ro, sizeof(ro));
if (hlen != 0) {
ro.ro_prepend = (u_char *)&dst.sa_data;
ro.ro_plen = hlen;
ro.ro_flags = RT_HAS_HEADER;
}
error = (*ifp->if_output)(ifp, m, &dst, &ro);
if (error)
d->bd_wdcount++;

View File

@ -665,6 +665,7 @@ int
flowtable_lookup(sa_family_t sa, struct mbuf *m, struct route *ro)
{
struct flentry *fle;
struct llentry *lle;
if (V_flowtable_enable == 0)
return (ENXIO);
@ -693,8 +694,15 @@ flowtable_lookup(sa_family_t sa, struct mbuf *m, struct route *ro)
}
ro->ro_rt = fle->f_rt;
ro->ro_lle = fle->f_lle;
ro->ro_flags |= RT_NORTREF;
lle = fle->f_lle;
if (lle != NULL && (lle->la_flags & LLE_VALID)) {
ro->ro_prepend = lle->r_linkdata;
ro->ro_plen = lle->r_hdrlen;
ro->ro_flags |= RT_MAY_LOOP;
if (lle->la_flags & LLE_IFADDR)
ro->ro_flags |= RT_L2_ME;
}
return (0);
}

View File

@ -161,6 +161,7 @@ static int ifconf(u_long, caddr_t);
static void if_freemulti(struct ifmultiaddr *);
static void if_grow(void);
static void if_input_default(struct ifnet *, struct mbuf *);
static int if_requestencap_default(struct ifnet *, struct if_encap_req *);
static void if_route(struct ifnet *, int flag, int fam);
static int if_setflag(struct ifnet *, int, int, int *, int);
static int if_transmit(struct ifnet *ifp, struct mbuf *m);
@ -673,6 +674,9 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
if (ifp->if_input == NULL)
ifp->if_input = if_input_default;
if (ifp->if_requestencap == NULL)
ifp->if_requestencap = if_requestencap_default;
if (!vmove) {
#ifdef MAC
mac_ifnet_create(ifp);
@ -3397,6 +3401,43 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
return (0);
}
/*
* Compat function for handling basic encapsulation requests.
* Not converted stacks (FDDI, IB, ..) supports traditional
* output model: ARP (and other similar L2 protocols) are handled
* inside output routine, arpresolve/nd6_resolve() returns MAC
* address instead of full prepend.
*
* This function creates calculated header==MAC for IPv4/IPv6 and
* returns EAFNOSUPPORT (which is then handled in ARP code) for other
* address families.
*/
static int
if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req)
{
if (req->rtype != IFENCAP_LL)
return (EOPNOTSUPP);
if (req->bufsize < req->lladdr_len)
return (ENOMEM);
switch (req->family) {
case AF_INET:
case AF_INET6:
break;
default:
return (EAFNOSUPPORT);
}
/* Copy lladdr to storage as is */
memmove(req->buf, req->lladdr, req->lladdr_len);
req->bufsize = req->lladdr_len;
req->lladdr_off = 0;
return (0);
}
/*
* The name argument must be a pointer to storage which will last as
* long as the interface does. For physical devices, the result of

View File

@ -113,6 +113,7 @@ static int ether_resolvemulti(struct ifnet *, struct sockaddr **,
#ifdef VIMAGE
static void ether_reassign(struct ifnet *, struct vnet *, char *);
#endif
static int ether_requestencap(struct ifnet *, struct if_encap_req *);
#define ETHER_IS_BROADCAST(addr) \
(bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
@ -135,6 +136,138 @@ update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst)
dst->m_pkthdr.csum_data = 0xffff;
}
/*
* Handle link-layer encapsulation requests.
*/
static int
ether_requestencap(struct ifnet *ifp, struct if_encap_req *req)
{
struct ether_header *eh;
struct arphdr *ah;
uint16_t etype;
const u_char *lladdr;
if (req->rtype != IFENCAP_LL)
return (EOPNOTSUPP);
if (req->bufsize < ETHER_HDR_LEN)
return (ENOMEM);
eh = (struct ether_header *)req->buf;
lladdr = req->lladdr;
req->lladdr_off = 0;
switch (req->family) {
case AF_INET:
etype = htons(ETHERTYPE_IP);
break;
case AF_INET6:
etype = htons(ETHERTYPE_IPV6);
break;
case AF_ARP:
ah = (struct arphdr *)req->hdata;
ah->ar_hrd = htons(ARPHRD_ETHER);
switch(ntohs(ah->ar_op)) {
case ARPOP_REVREQUEST:
case ARPOP_REVREPLY:
etype = htons(ETHERTYPE_REVARP);
break;
case ARPOP_REQUEST:
case ARPOP_REPLY:
default:
etype = htons(ETHERTYPE_ARP);
break;
}
if (req->flags & IFENCAP_FLAG_BROADCAST)
lladdr = ifp->if_broadcastaddr;
break;
default:
return (EAFNOSUPPORT);
}
memcpy(&eh->ether_type, &etype, sizeof(eh->ether_type));
memcpy(eh->ether_dhost, lladdr, ETHER_ADDR_LEN);
memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
req->bufsize = sizeof(struct ether_header);
return (0);
}
static int
ether_resolve_addr(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, struct route *ro, u_char *phdr,
uint32_t *pflags)
{
struct ether_header *eh;
struct rtentry *rt;
uint32_t lleflags = 0;
int error = 0;
#if defined(INET) || defined(INET6)
uint16_t etype;
#endif
eh = (struct ether_header *)phdr;
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if ((m->m_flags & (M_BCAST | M_MCAST)) == 0)
error = arpresolve(ifp, 0, m, dst, phdr, &lleflags);
else {
if (m->m_flags & M_BCAST)
memcpy(eh->ether_dhost, ifp->if_broadcastaddr,
ETHER_ADDR_LEN);
else {
const struct in_addr *a;
a = &(((const struct sockaddr_in *)dst)->sin_addr);
ETHER_MAP_IP_MULTICAST(a, eh->ether_dhost);
}
etype = htons(ETHERTYPE_IP);
memcpy(&eh->ether_type, &etype, sizeof(etype));
memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
}
break;
#endif
#ifdef INET6
case AF_INET6:
if ((m->m_flags & M_MCAST) == 0)
error = nd6_resolve(ifp, 0, m, dst, phdr, &lleflags);
else {
const struct in6_addr *a6;
a6 = &(((const struct sockaddr_in6 *)dst)->sin6_addr);
ETHER_MAP_IPV6_MULTICAST(a6, eh->ether_dhost);
etype = htons(ETHERTYPE_IPV6);
memcpy(&eh->ether_type, &etype, sizeof(etype));
memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
}
break;
#endif
default:
if_printf(ifp, "can't handle af%d\n", dst->sa_family);
if (m != NULL)
m_freem(m);
return (EAFNOSUPPORT);
}
if (error == EHOSTDOWN) {
rt = (ro != NULL) ? ro->ro_rt : NULL;
if (rt != NULL && (rt->rt_flags & RTF_GATEWAY) != 0)
error = EHOSTUNREACH;
}
if (error != 0)
return (error);
*pflags = RT_MAY_LOOP;
if (lleflags & LLE_IFADDR)
*pflags |= RT_L2_ME;
return (0);
}
/*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
@ -145,27 +278,20 @@ int
ether_output(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, struct route *ro)
{
short type;
int error = 0, hdrcmplt = 0;
u_char edst[ETHER_ADDR_LEN];
struct llentry *lle = NULL;
struct rtentry *rt0 = NULL;
int error = 0;
char linkhdr[ETHER_HDR_LEN], *phdr;
struct ether_header *eh;
struct pf_mtag *t;
int loop_copy = 1;
int hlen; /* link layer header length */
int is_gw = 0;
uint32_t pflags = 0;
uint32_t pflags;
phdr = NULL;
pflags = 0;
if (ro != NULL) {
if (!(m->m_flags & (M_BCAST | M_MCAST))) {
lle = ro->ro_lle;
if (lle != NULL)
pflags = lle->la_flags;
}
rt0 = ro->ro_rt;
if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
phdr = ro->ro_prepend;
hlen = ro->ro_plen;
pflags = ro->ro_flags;
}
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@ -180,94 +306,31 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
senderr(ENETDOWN);
hlen = ETHER_HDR_LEN;
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if (lle != NULL && (pflags & LLE_VALID) != 0)
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
else
error = arpresolve(ifp, is_gw, m, dst, edst, &pflags);
if (error)
if (phdr == NULL) {
/* No prepend data supplied. Try to calculate ourselves. */
phdr = linkhdr;
hlen = ETHER_HDR_LEN;
error = ether_resolve_addr(ifp, m, dst, ro, phdr, &pflags);
if (error != 0)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
break;
case AF_ARP:
{
struct arphdr *ah;
ah = mtod(m, struct arphdr *);
ah->ar_hrd = htons(ARPHRD_ETHER);
loop_copy = 0; /* if this is for us, don't do it */
switch(ntohs(ah->ar_op)) {
case ARPOP_REVREQUEST:
case ARPOP_REVREPLY:
type = htons(ETHERTYPE_REVARP);
break;
case ARPOP_REQUEST:
case ARPOP_REPLY:
default:
type = htons(ETHERTYPE_ARP);
break;
}
if (m->m_flags & M_BCAST)
bcopy(ifp->if_broadcastaddr, edst, ETHER_ADDR_LEN);
else
bcopy(ar_tha(ah), edst, ETHER_ADDR_LEN);
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (lle != NULL && (pflags & LLE_VALID))
memcpy(edst, &lle->ll_addr.mac16, sizeof(edst));
else
error = nd6_resolve(ifp, is_gw, m, dst, (u_char *)edst,
&pflags);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IPV6);
break;
#endif
case pseudo_AF_HDRCMPLT:
{
const struct ether_header *eh;
hdrcmplt = 1;
/* FALLTHROUGH */
case AF_UNSPEC:
loop_copy = 0; /* if this is for us, don't do it */
eh = (const struct ether_header *)dst->sa_data;
(void)memcpy(edst, eh->ether_dhost, sizeof (edst));
type = eh->ether_type;
break;
}
default:
if_printf(ifp, "can't handle af%d\n", dst->sa_family);
senderr(EAFNOSUPPORT);
}
if ((pflags & LLE_IFADDR) != 0) {
if ((pflags & RT_L2_ME) != 0) {
update_mbuf_csumflags(m, m);
return (if_simloop(ifp, m, dst->sa_family, 0));
}
loop_copy = pflags & RT_MAY_LOOP;
/*
* Add local net header. If no space in first mbuf,
* allocate another.
*/
M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT);
M_PREPEND(m, hlen, M_NOWAIT);
if (m == NULL)
senderr(ENOBUFS);
eh = mtod(m, struct ether_header *);
if (hdrcmplt == 0) {
memcpy(&eh->ether_type, &type, sizeof(eh->ether_type));
memcpy(eh->ether_dhost, edst, sizeof (edst));
memcpy(eh->ether_shost, IF_LLADDR(ifp),sizeof(eh->ether_shost));
if ((pflags & RT_HAS_HEADER) == 0) {
eh = mtod(m, struct ether_header *);
memcpy(eh, phdr, hlen);
}
/*
@ -279,34 +342,27 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
* on the wire). However, we don't do that here for security
* reasons and compatibility with the original behavior.
*/
if ((ifp->if_flags & IFF_SIMPLEX) && loop_copy &&
if ((m->m_flags & M_BCAST) && loop_copy && (ifp->if_flags & IFF_SIMPLEX) &&
((t = pf_find_mtag(m)) == NULL || !t->routed)) {
if (m->m_flags & M_BCAST) {
struct mbuf *n;
struct mbuf *n;
/*
* Because if_simloop() modifies the packet, we need a
* writable copy through m_dup() instead of a readonly
* one as m_copy[m] would give us. The alternative would
* be to modify if_simloop() to handle the readonly mbuf,
* but performancewise it is mostly equivalent (trading
* extra data copying vs. extra locking).
*
* XXX This is a local workaround. A number of less
* often used kernel parts suffer from the same bug.
* See PR kern/105943 for a proposed general solution.
*/
if ((n = m_dup(m, M_NOWAIT)) != NULL) {
update_mbuf_csumflags(m, n);
(void)if_simloop(ifp, n, dst->sa_family, hlen);
} else
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
} else if (bcmp(eh->ether_dhost, eh->ether_shost,
ETHER_ADDR_LEN) == 0) {
update_mbuf_csumflags(m, m);
(void) if_simloop(ifp, m, dst->sa_family, hlen);
return (0); /* XXX */
}
/*
* Because if_simloop() modifies the packet, we need a
* writable copy through m_dup() instead of a readonly
* one as m_copy[m] would give us. The alternative would
* be to modify if_simloop() to handle the readonly mbuf,
* but performancewise it is mostly equivalent (trading
* extra data copying vs. extra locking).
*
* XXX This is a local workaround. A number of less
* often used kernel parts suffer from the same bug.
* See PR kern/105943 for a proposed general solution.
*/
if ((n = m_dup(m, M_NOWAIT)) != NULL) {
update_mbuf_csumflags(m, n);
(void)if_simloop(ifp, n, dst->sa_family, hlen);
} else
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
}
/*
@ -798,6 +854,7 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
ifp->if_output = ether_output;
ifp->if_input = ether_input;
ifp->if_resolvemulti = ether_resolvemulti;
ifp->if_requestencap = ether_requestencap;
#ifdef VIMAGE
ifp->if_reassign = ether_reassign;
#endif

View File

@ -529,7 +529,6 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn)
struct gif_softc *sc;
struct ether_header *eh;
struct ifnet *oldifp;
uint32_t gif_options;
int isr, n, af;
if (ifp == NULL) {
@ -538,7 +537,6 @@ gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn)
return;
}
sc = ifp->if_softc;
gif_options = sc->gif_options;
m->m_pkthdr.rcvif = ifp;
m_clrprotoflags(m);
switch (proto) {

View File

@ -682,7 +682,10 @@ gre_input(struct mbuf **mp, int *offp, int proto)
struct grehdr *gh;
struct ifnet *ifp;
struct mbuf *m;
uint32_t *opts, key;
uint32_t *opts;
#ifdef notyet
uint32_t key;
#endif
uint16_t flags;
int hlen, isr, af;
@ -715,17 +718,28 @@ gre_input(struct mbuf **mp, int *offp, int proto)
opts++;
}
if (flags & GRE_FLAGS_KP) {
#ifdef notyet
/*
* XXX: The current implementation uses the key only for outgoing
* packets. But we can check the key value here, or even in the
* encapcheck function.
*/
key = ntohl(*opts);
#endif
hlen += sizeof(uint32_t);
opts++;
}
#ifdef notyet
} else
key = 0;
/*
if (sc->gre_key != 0 && (key != sc->gre_key || key != 0))
goto drop;
*/
#endif
if (flags & GRE_FLAGS_SP) {
/* seq = ntohl(*opts); */
#ifdef notyet
seq = ntohl(*opts);
#endif
hlen += sizeof(uint32_t);
}
switch (ntohs(gh->gre_proto)) {

View File

@ -278,10 +278,12 @@ lltable_drop_entry_queue(struct llentry *lle)
void
lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
const char *lladdr)
const char *linkhdr, size_t linkhdrsize, int lladdr_off)
{
bcopy(lladdr, &lle->ll_addr, ifp->if_addrlen);
memcpy(lle->r_linkdata, linkhdr, linkhdrsize);
lle->r_hdrlen = linkhdrsize;
lle->ll_addr = &lle->r_linkdata[lladdr_off];
lle->la_flags |= LLE_VALID;
lle->r_flags |= RLLE_VALID;
}
@ -296,7 +298,7 @@ lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
*/
int
lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
const char *lladdr)
const char *linkhdr, size_t linkhdrsize, int lladdr_off)
{
/* Perform real LLE update */
@ -318,7 +320,7 @@ lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
}
/* Update data */
lltable_set_entry_addr(ifp, lle, lladdr);
lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off);
IF_AFDATA_WUNLOCK(ifp);
@ -327,6 +329,84 @@ lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
return (1);
}
/*
* Helper function used to pre-compute full/partial link-layer
* header data suitable for feeding into if_output().
*/
int
lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
char *buf, size_t *bufsize, int *lladdr_off)
{
struct if_encap_req ereq;
int error;
bzero(buf, *bufsize);
bzero(&ereq, sizeof(ereq));
ereq.buf = buf;
ereq.bufsize = *bufsize;
ereq.rtype = IFENCAP_LL;
ereq.family = family;
ereq.lladdr = lladdr;
ereq.lladdr_len = ifp->if_addrlen;
error = ifp->if_requestencap(ifp, &ereq);
if (error == 0) {
*bufsize = ereq.bufsize;
*lladdr_off = ereq.lladdr_off;
}
return (error);
}
/*
* Update link-layer header for given @lle after
* interface lladdr was changed.
*/
static int
llentry_update_ifaddr(struct lltable *llt, struct llentry *lle, void *farg)
{
struct ifnet *ifp;
u_char linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
u_char *lladdr;
int lladdr_off;
ifp = (struct ifnet *)farg;
lladdr = lle->ll_addr;
LLE_WLOCK(lle);
if ((lle->la_flags & LLE_VALID) == 0) {
LLE_WUNLOCK(lle);
return (0);
}
if ((lle->la_flags & LLE_IFADDR) != 0)
lladdr = IF_LLADDR(ifp);
linkhdrsize = sizeof(linkhdr);
lltable_calc_llheader(ifp, llt->llt_af, lladdr, linkhdr, &linkhdrsize,
&lladdr_off);
memcpy(lle->r_linkdata, linkhdr, linkhdrsize);
LLE_WUNLOCK(lle);
return (0);
}
/*
* Update all calculated headers for given @llt
*/
void
lltable_update_ifaddr(struct lltable *llt)
{
if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
return;
IF_AFDATA_WLOCK(llt->llt_ifp);
lltable_foreach_lle(llt, llentry_update_ifaddr, llt->llt_ifp);
IF_AFDATA_WUNLOCK(llt->llt_ifp);
}
/*
*
* Performes generic cleanup routines and frees lle.
@ -642,6 +722,9 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
struct ifnet *ifp;
struct lltable *llt;
struct llentry *lle, *lle_tmp;
uint8_t linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
int lladdr_off;
u_int laflags = 0;
int error;
@ -677,11 +760,14 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
if (lle == NULL)
return (ENOMEM);
bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, dst->sa_family, LLADDR(dl),
linkhdr, &linkhdrsize, &lladdr_off) != 0)
return (EINVAL);
lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
lladdr_off);
if ((rtm->rtm_flags & RTF_ANNOUNCE))
lle->la_flags |= LLE_PUB;
lle->la_flags |= LLE_VALID;
lle->r_flags |= RLLE_VALID;
lle->la_expire = rtm->rtm_rmx.rmx_expire;
laflags = lle->la_flags;
@ -767,7 +853,7 @@ llatbl_lle_show(struct llentry_sa *la)
db_printf(" ln_router=%u\n", lle->ln_router);
db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick);
db_printf(" lle_refcnt=%d\n", lle->lle_refcnt);
bcopy(&lle->ll_addr.mac16, octet, sizeof(octet));
bcopy(lle->ll_addr, octet, sizeof(octet));
db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]);
db_printf(" lle_timer=%p\n", &lle->lle_timer);

View File

@ -48,6 +48,7 @@ extern struct rwlock lltable_rwlock;
#define LLTABLE_WUNLOCK() rw_wunlock(&lltable_rwlock)
#define LLTABLE_LOCK_ASSERT() rw_assert(&lltable_rwlock, RA_LOCKED)
#define LLE_MAX_LINKHDR 24 /* Full IB header */
/*
* Code referencing llentry must at least hold
* a shared lock
@ -58,14 +59,11 @@ struct llentry {
struct in_addr addr4;
struct in6_addr addr6;
} r_l3addr;
union {
uint64_t mac_aligned;
uint16_t mac16[3];
uint8_t mac8[20]; /* IB needs 20 bytes. */
} ll_addr;
char r_linkdata[LLE_MAX_LINKHDR]; /* L2 data */
uint8_t r_hdrlen; /* length for LL header */
uint8_t spare0[3];
uint16_t r_flags; /* LLE runtime flags */
uint16_t r_skip_req; /* feedback from fast path */
uint64_t spare1;
struct lltable *lle_tbl;
struct llentries *lle_head;
@ -82,6 +80,7 @@ struct llentry {
time_t lle_remtime; /* Real time remaining */
time_t lle_hittime; /* Time when r_skip_req was unset */
int lle_refcnt;
char *ll_addr; /* link-layer address */
LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */
struct callout lle_timer;
@ -198,6 +197,8 @@ MALLOC_DECLARE(M_LLTABLE);
/* LLE request flags */
#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
#define LLE_UNLOCKED 0x4000 /* return lle unlocked */
#define LLE_ADDRONLY 0x4000 /* return lladdr instead of full header */
#define LLE_CREATE 0x8000 /* hint to avoid lle lookup */
/* LLE flags used by fastpath code */
#define RLLE_VALID 0x0001 /* entry is valid */
@ -223,10 +224,13 @@ struct llentry *llentry_alloc(struct ifnet *, struct lltable *,
/* helper functions */
size_t lltable_drop_entry_queue(struct llentry *);
void lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
const char *lladdr);
const char *linkhdr, size_t linkhdrsize, int lladdr_off);
int lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
const char *lladdr);
const char *linkhdr, size_t linkhdrsize, int lladdr_off);
int lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
char *buf, size_t *bufsize, int *lladdr_off);
void lltable_update_ifaddr(struct lltable *llt);
struct llentry *lltable_alloc_entry(struct lltable *llt, u_int flags,
const struct sockaddr *l4addr);
void lltable_free_entry(struct lltable *llt, struct llentry *lle);

View File

@ -134,6 +134,48 @@ struct ifnet_hw_tsomax {
u_int tsomaxsegsize; /* TSO maximum segment size in bytes */
};
/* Interface encap request types */
typedef enum {
IFENCAP_LL = 1 /* pre-calculate link-layer header */
} ife_type;
/*
* The structure below allows to request various pre-calculated L2/L3 headers
* for different media. Requests varies by type (rtype field).
*
* IFENCAP_LL type: pre-calculates link header based on address family
* and destination lladdr.
*
* Input data fields:
* buf: pointer to destination buffer
* bufsize: buffer size
* flags: IFENCAP_FLAG_BROADCAST if destination is broadcast
* family: address family defined by AF_ constant.
* lladdr: pointer to link-layer address
* lladdr_len: length of link-layer address
* hdata: pointer to L3 header (optional, used for ARP requests).
* Output data fields:
* buf: encap data is stored here
* bufsize: resulting encap length is stored here
* lladdr_off: offset of link-layer address from encap hdr start
* hdata: L3 header may be altered if necessary
*/
struct if_encap_req {
u_char *buf; /* Destination buffer (w) */
size_t bufsize; /* size of provided buffer (r) */
ife_type rtype; /* request type (r) */
uint32_t flags; /* Request flags (r) */
int family; /* Address family AF_* (r) */
int lladdr_off; /* offset from header start (w) */
int lladdr_len; /* lladdr length (r) */
char *lladdr; /* link-level address pointer (r) */
char *hdata; /* Upper layer header data (rw) */
};
#define IFENCAP_FLAG_BROADCAST 0x02 /* Destination is broadcast */
/*
* Structure defining a network interface.
*
@ -235,6 +277,8 @@ struct ifnet {
void (*if_reassign) /* reassign to vnet routine */
(struct ifnet *, struct vnet *, char *);
if_get_counter_t if_get_counter; /* get counter values */
int (*if_requestencap) /* make link header from request */
(struct ifnet *, struct if_encap_req *);
/* Statistics. */
counter_u64_t if_counters[IFCOUNTERS];

View File

@ -51,14 +51,21 @@
*/
struct route {
struct rtentry *ro_rt;
struct llentry *ro_lle;
struct in_ifaddr *ro_ia;
int ro_flags;
char *ro_prepend;
uint16_t ro_plen;
uint16_t ro_flags;
struct sockaddr ro_dst;
};
#define RT_L2_ME_BIT 2 /* dst L2 addr is our address */
#define RT_MAY_LOOP_BIT 3 /* dst may require loop copy */
#define RT_HAS_HEADER_BIT 4 /* mbuf already have its header prepended */
#define RT_CACHING_CONTEXT 0x1 /* XXX: not used anywhere */
#define RT_NORTREF 0x2 /* doesn't hold reference on ro_rt */
#define RT_L2_ME (1 << RT_L2_ME_BIT)
#define RT_MAY_LOOP (1 << RT_MAY_LOOP_BIT)
#define RT_HAS_HEADER (1 << RT_HAS_HEADER_BIT)
struct rt_metrics {
u_long rmx_locks; /* Kernel must leave these values alone */

View File

@ -281,6 +281,37 @@ arptimer(void *arg)
CURVNET_RESTORE();
}
/*
* Stores link-layer header for @ifp in format suitable for if_output()
* into buffer @buf. Resulting header length is stored in @bufsize.
*
* Returns 0 on success.
*/
static int
arp_fillheader(struct ifnet *ifp, struct arphdr *ah, int bcast, u_char *buf,
size_t *bufsize)
{
struct if_encap_req ereq;
int error;
bzero(buf, *bufsize);
bzero(&ereq, sizeof(ereq));
ereq.buf = buf;
ereq.bufsize = *bufsize;
ereq.rtype = IFENCAP_LL;
ereq.family = AF_ARP;
ereq.lladdr = ar_tha(ah);
ereq.hdata = (u_char *)ah;
if (bcast)
ereq.flags = IFENCAP_FLAG_BROADCAST;
error = ifp->if_requestencap(ifp, &ereq);
if (error == 0)
*bufsize = ereq.bufsize;
return (error);
}
/*
* Broadcast an ARP request. Caller specifies:
* - arp header source ip address
@ -295,6 +326,10 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
struct arphdr *ah;
struct sockaddr sa;
u_char *carpaddr = NULL;
uint8_t linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
struct route ro;
int error;
if (sip == NULL) {
/*
@ -350,12 +385,28 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
bcopy(tip, ar_tpa(ah), ah->ar_pln);
sa.sa_family = AF_ARP;
sa.sa_len = 2;
/* Calculate link header for sending frame */
bzero(&ro, sizeof(ro));
linkhdrsize = sizeof(linkhdr);
error = arp_fillheader(ifp, ah, 1, linkhdr, &linkhdrsize);
if (error != 0 && error != EAFNOSUPPORT) {
ARP_LOG(LOG_ERR, "Failed to calculate ARP header on %s: %d\n",
if_name(ifp), error);
return;
}
ro.ro_prepend = linkhdr;
ro.ro_plen = linkhdrsize;
ro.ro_flags = 0;
m->m_flags |= M_BCAST;
m_clrprotoflags(m); /* Avoid confusing lower layers. */
(*ifp->if_output)(ifp, m, &sa, NULL);
(*ifp->if_output)(ifp, m, &sa, &ro);
ARPSTAT_INC(txrequests);
}
/*
* Resolve an IP address into an ethernet address - heavy version.
* Used internally by arpresolve().
@ -368,18 +419,20 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
* Note that m_freem() handles NULL.
*/
static int
arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m,
arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, uint32_t *pflags)
{
struct llentry *la = NULL, *la_tmp;
struct mbuf *curr = NULL;
struct mbuf *next = NULL;
int error, renew;
char *lladdr;
int ll_len;
if (pflags != NULL)
*pflags = 0;
if (create == 0) {
if ((flags & LLE_CREATE) == 0) {
IF_AFDATA_RLOCK(ifp);
la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
IF_AFDATA_RUNLOCK(ifp);
@ -413,7 +466,14 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m,
if ((la->la_flags & LLE_VALID) &&
((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
if (flags & LLE_ADDRONLY) {
lladdr = la->ll_addr;
ll_len = ifp->if_addrlen;
} else {
lladdr = la->r_linkdata;
ll_len = la->r_hdrlen;
}
bcopy(lladdr, desten, ll_len);
/* Check if we have feedback request from arptimer() */
if (la->r_skip_req != 0) {
@ -485,15 +545,31 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int create, struct mbuf *m,
/*
* Resolve an IP address into an ethernet address.
*/
int
arpresolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
char *desten, uint32_t *pflags)
{
int error;
flags |= LLE_ADDRONLY;
error = arpresolve_full(ifp, 0, flags, NULL, dst, desten, pflags);
return (error);
}
/*
* Lookups link header based on an IP address.
* On input:
* ifp is the interface we use
* is_gw != 0 if @dst represents gateway to some destination
* m is the mbuf. May be NULL if we don't have a packet.
* dst is the next hop,
* desten is the storage to put LL address.
* desten is the storage to put LL header.
* flags returns subset of lle flags: LLE_VALID | LLE_IFADDR
*
* On success, desten and flags are filled in and the function returns 0;
* On success, full/partial link header and flags are filled in and
* the function returns 0.
* If the packet must be held pending resolution, we return EWOULDBLOCK
* On other errors, we return the corresponding error code.
* Note that m_freem() handles NULL.
@ -525,7 +601,7 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
la = lla_lookup(LLTABLE(ifp), LLE_UNLOCKED, dst);
if (la != NULL && (la->r_flags & RLLE_VALID) != 0) {
/* Entry found, let's copy lle info */
bcopy(&la->ll_addr, desten, ifp->if_addrlen);
bcopy(la->r_linkdata, desten, la->r_hdrlen);
if (pflags != NULL)
*pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR);
/* Check if we have feedback request from arptimer() */
@ -539,7 +615,8 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
}
IF_AFDATA_RUNLOCK(ifp);
return (arpresolve_full(ifp, is_gw, 1, m, dst, desten, pflags));
return (arpresolve_full(ifp, is_gw, la == NULL ? LLE_CREATE : 0, m, dst,
desten, pflags));
}
/*
@ -683,6 +760,11 @@ in_arpinput(struct mbuf *m)
struct sockaddr_in sin;
struct sockaddr *dst;
struct nhop4_basic nh4;
uint8_t linkhdr[LLE_MAX_LINKHDR];
struct route ro;
size_t linkhdrsize;
int lladdr_off;
int error;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
@ -850,8 +932,14 @@ in_arpinput(struct mbuf *m)
else if (itaddr.s_addr == myaddr.s_addr) {
/*
* Request/reply to our address, but no lle exists yet.
* Try to create new llentry.
* Calculate full link prepend to use in lle.
*/
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr,
&linkhdrsize, &lladdr_off) != 0)
goto reply;
/* Allocate new entry */
la = lltable_alloc_entry(LLTABLE(ifp), 0, dst);
if (la == NULL) {
@ -863,7 +951,8 @@ in_arpinput(struct mbuf *m)
*/
goto reply;
}
lltable_set_entry_addr(ifp, la, ar_sha(ah));
lltable_set_entry_addr(ifp, la, linkhdr, linkhdrsize,
lladdr_off);
IF_AFDATA_WLOCK(ifp);
LLE_WLOCK(la);
@ -921,7 +1010,7 @@ in_arpinput(struct mbuf *m)
if ((lle != NULL) && (lle->la_flags & LLE_PUB)) {
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
(void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);
(void)memcpy(ar_sha(ah), lle->ll_addr, ah->ar_hln);
LLE_RUNLOCK(lle);
} else {
@ -991,8 +1080,29 @@ in_arpinput(struct mbuf *m)
m->m_pkthdr.rcvif = NULL;
sa.sa_family = AF_ARP;
sa.sa_len = 2;
/* Calculate link header for sending frame */
bzero(&ro, sizeof(ro));
linkhdrsize = sizeof(linkhdr);
error = arp_fillheader(ifp, ah, 0, linkhdr, &linkhdrsize);
/*
* arp_fillheader() may fail due to lack of support inside encap request
* routing. This is not necessary an error, AF_ARP can/should be handled
* by if_output().
*/
if (error != 0 && error != EAFNOSUPPORT) {
ARP_LOG(LOG_ERR, "Failed to calculate ARP header on %s: %d\n",
if_name(ifp), error);
return;
}
ro.ro_prepend = linkhdr;
ro.ro_plen = linkhdrsize;
ro.ro_flags = 0;
m_clrprotoflags(m); /* Avoid confusing lower layers. */
(*ifp->if_output)(ifp, m, &sa, NULL);
(*ifp->if_output)(ifp, m, &sa, &ro);
ARPSTAT_INC(txreplies);
return;
@ -1011,6 +1121,9 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp
{
struct sockaddr sa;
struct mbuf *m_hold, *m_hold_next;
uint8_t linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
int lladdr_off;
LLE_WLOCK_ASSERT(la);
@ -1027,7 +1140,7 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp
return;
}
if ((la->la_flags & LLE_VALID) &&
bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) {
bcmp(ar_sha(ah), la->ll_addr, ifp->if_addrlen)) {
if (la->la_flags & LLE_STATIC) {
LLE_WUNLOCK(la);
if (log_arp_permanent_modify)
@ -1050,31 +1163,19 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp
}
}
/* Calculate full link prepend to use in lle */
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr,
&linkhdrsize, &lladdr_off) != 0)
return;
/* Check if something has changed */
if (memcmp(&la->ll_addr, ar_sha(ah), ifp->if_addrlen) != 0 ||
if (memcmp(la->r_linkdata, linkhdr, linkhdrsize) != 0 ||
(la->la_flags & LLE_VALID) == 0) {
/* Perform real LLE update */
/* use afdata WLOCK to update fields */
LLE_ADDREF(la);
LLE_WUNLOCK(la);
IF_AFDATA_WLOCK(ifp);
LLE_WLOCK(la);
/*
* Since we droppped LLE lock, other thread might have deleted
* this lle. Check and return
*/
if ((la->la_flags & LLE_DELETED) != 0) {
IF_AFDATA_WUNLOCK(ifp);
LLE_FREE_LOCKED(la);
/* Try to perform LLE update */
if (lltable_try_set_entry_addr(ifp, la, linkhdr, linkhdrsize,
lladdr_off) == 0)
return;
}
/* Update data */
lltable_set_entry_addr(ifp, la, ar_sha(ah));
IF_AFDATA_WUNLOCK(ifp);
LLE_REMREF(la);
/* Clear fast path feedback request if set */
la->r_skip_req = 0;
@ -1215,10 +1316,12 @@ arp_handle_ifllchange(struct ifnet *ifp)
/*
* A handler for interface link layer address change event.
*/
static __noinline void
static void
arp_iflladdr(void *arg __unused, struct ifnet *ifp)
{
lltable_update_ifaddr(LLTABLE(ifp));
if ((ifp->if_flags & IFF_UP) != 0)
arp_handle_ifllchange(ifp);
}
@ -1231,5 +1334,8 @@ arp_init(void)
if (IS_DEFAULT_VNET(curvnet))
iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
if (IS_DEFAULT_VNET(curvnet))
iflladdr_tag = EVENTHANDLER_REGISTER(iflladdr_event,
arp_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
}
SYSINIT(arp, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY, arp_init, 0);

View File

@ -114,6 +114,8 @@ extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
struct ifaddr;
int arpresolve_addr(struct ifnet *ifp, int flags,
const struct sockaddr *dst, char *desten, uint32_t *pflags);
int arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
const struct sockaddr *dst, u_char *desten, uint32_t *pflags);
void arprequest(struct ifnet *, const struct in_addr *,

View File

@ -1240,6 +1240,9 @@ in_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr *l3addr
const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
struct ifnet *ifp = llt->llt_ifp;
struct llentry *lle;
char linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
int lladdr_off;
KASSERT(l3addr->sa_family == AF_INET,
("sin_family %d", l3addr->sa_family));
@ -1262,7 +1265,12 @@ in_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr *l3addr
if (flags & LLE_STATIC)
lle->r_flags |= RLLE_VALID;
if ((flags & LLE_IFADDR) == LLE_IFADDR) {
lltable_set_entry_addr(ifp, lle, IF_LLADDR(ifp));
linkhdrsize = LLE_MAX_LINKHDR;
if (lltable_calc_llheader(ifp, AF_INET, IF_LLADDR(ifp),
linkhdr, &linkhdrsize, &lladdr_off) != 0)
return (NULL);
lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
lladdr_off);
lle->la_flags |= LLE_STATIC;
lle->r_flags |= (RLLE_VALID | RLLE_IFADDR);
}
@ -1349,7 +1357,7 @@ in_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
sdl->sdl_type = ifp->if_type;
if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
sdl->sdl_alen = ifp->if_addrlen;
bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
bcopy(lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
} else {
sdl->sdl_alen = 0;
bzero(LLADDR(sdl), ifp->if_addrlen);

View File

@ -567,7 +567,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
RO_RTFREE(ro);
if (have_ia_ref)
ifa_free(&ia->ia_ifa);
ro->ro_lle = NULL;
ro->ro_prepend = NULL;
rte = NULL;
gw = dst;
ip = mtod(m, struct ip *);

View File

@ -428,7 +428,7 @@ toe_lle_event(void *arg __unused, struct llentry *lle, int evt)
KASSERT(lle->la_flags & LLE_VALID,
("%s: %p resolved but not valid?", __func__, lle));
lladdr = (uint8_t *)&lle->ll_addr;
lladdr = (uint8_t *)lle->ll_addr;
#ifdef VLAN_TAG
VLAN_TAG(ifp, &vtag);
#endif

View File

@ -2632,7 +2632,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
nd_opt->nd_opt_len = len >> 3;
lladdr = (char *)(nd_opt + 1);
bcopy(&ln->ll_addr, lladdr, ifp->if_addrlen);
bcopy(ln->ll_addr, lladdr, ifp->if_addrlen);
p += len;
}
}

View File

@ -1552,7 +1552,7 @@ in6ifa_llaonifp(struct ifnet *ifp)
if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
return (NULL);
if_addr_rlock(ifp);
IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@ -1562,7 +1562,7 @@ in6ifa_llaonifp(struct ifnet *ifp)
IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr))
break;
}
if_addr_runlock(ifp);
IF_ADDR_RUNLOCK(ifp);
return ((struct in6_ifaddr *)ifa);
}
@ -2245,6 +2245,9 @@ in6_lltable_alloc(struct lltable *llt, u_int flags,
const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
struct ifnet *ifp = llt->llt_ifp;
struct llentry *lle;
char linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
int lladdr_off;
KASSERT(l3addr->sa_family == AF_INET6,
("sin_family %d", l3addr->sa_family));
@ -2265,7 +2268,12 @@ in6_lltable_alloc(struct lltable *llt, u_int flags,
}
lle->la_flags = flags;
if ((flags & LLE_IFADDR) == LLE_IFADDR) {
lltable_set_entry_addr(ifp, lle, IF_LLADDR(ifp));
linkhdrsize = LLE_MAX_LINKHDR;
if (lltable_calc_llheader(ifp, AF_INET6, IF_LLADDR(ifp),
linkhdr, &linkhdrsize, &lladdr_off) != 0)
return (NULL);
lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
lladdr_off);
lle->la_flags |= LLE_STATIC;
}

View File

@ -375,9 +375,9 @@ extern const struct in6_addr in6addr_linklocal_allv2routers;
#if __BSD_VISIBLE
struct route_in6 {
struct rtentry *ro_rt;
struct llentry *ro_lle;
struct in6_addr *ro_ia6;
int ro_flags;
char *ro_prepend;
uint16_t ro_plen;
uint16_t ro_flags;
struct sockaddr_in6 ro_dst;
};
#endif

View File

@ -1830,6 +1830,7 @@ do { \
case IPV6_RSSBUCKETID:
case IPV6_RECVRSSBUCKETID:
#endif
case IPV6_BINDMULTI:
switch (optname) {
case IPV6_RECVHOPOPTS:

View File

@ -111,7 +111,7 @@ VNET_DEFINE(int, nd6_debug) = 1;
VNET_DEFINE(int, nd6_debug) = 0;
#endif
static eventhandler_tag lle_event_eh;
static eventhandler_tag lle_event_eh, iflladdr_event_eh;
/* for debugging? */
#if 0
@ -137,7 +137,7 @@ static void nd6_llinfo_timer(void *);
static void nd6_llinfo_settimer_locked(struct llentry *, long);
static void clear_llinfo_pqueue(struct llentry *);
static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int nd6_resolve_slow(struct ifnet *, struct mbuf *,
static int nd6_resolve_slow(struct ifnet *, int, struct mbuf *,
const struct sockaddr_in6 *, u_char *, uint32_t *);
static int nd6_need_cache(struct ifnet *);
@ -188,7 +188,7 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt)
gw.sdl_index = ifp->if_index;
gw.sdl_type = ifp->if_type;
if (evt == LLENTRY_RESOLVED)
bcopy(&lle->ll_addr, gw.sdl_data, ifp->if_addrlen);
bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen);
rtinfo.rti_info[RTAX_DST] = (struct sockaddr *)&dst;
rtinfo.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&gw;
rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY;
@ -196,6 +196,16 @@ nd6_lle_event(void *arg __unused, struct llentry *lle, int evt)
type == RTM_ADD ? RTF_UP: 0), 0, RT_DEFAULT_FIB);
}
/*
* A handler for interface link layer address change event.
*/
static void
nd6_iflladdr(void *arg __unused, struct ifnet *ifp)
{
lltable_update_ifaddr(LLTABLE6(ifp));
}
void
nd6_init(void)
{
@ -211,9 +221,12 @@ nd6_init(void)
nd6_slowtimo, curvnet);
nd6_dad_init();
if (IS_DEFAULT_VNET(curvnet))
if (IS_DEFAULT_VNET(curvnet)) {
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event,
NULL, EVENTHANDLER_PRI_ANY);
iflladdr_event_eh = EVENTHANDLER_REGISTER(iflladdr_event,
nd6_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
}
}
#ifdef VIMAGE
@ -223,8 +236,10 @@ nd6_destroy()
callout_drain(&V_nd6_slowtimo_ch);
callout_drain(&V_nd6_timer_ch);
if (IS_DEFAULT_VNET(curvnet))
if (IS_DEFAULT_VNET(curvnet)) {
EVENTHANDLER_DEREGISTER(lle_event, lle_event_eh);
EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_event_eh);
}
}
#endif
@ -1844,6 +1859,9 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
uint16_t router = 0;
struct sockaddr_in6 sin6;
struct mbuf *chain = NULL;
u_char linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
int lladdr_off;
IF_AFDATA_UNLOCK_ASSERT(ifp);
@ -1878,8 +1896,15 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
* Since we already know all the data for the new entry,
* fill it before insertion.
*/
if (lladdr != NULL)
lltable_set_entry_addr(ifp, ln, lladdr);
if (lladdr != NULL) {
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
linkhdr, &linkhdrsize, &lladdr_off) != 0)
return;
lltable_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
lladdr_off);
}
IF_AFDATA_WLOCK(ifp);
LLE_WLOCK(ln);
/* Prefer any existing lle over newly-created one */
@ -1911,7 +1936,7 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
if (olladdr && lladdr) {
llchange = bcmp(lladdr, &ln->ll_addr,
llchange = bcmp(lladdr, ln->ll_addr,
ifp->if_addrlen);
} else if (!olladdr && lladdr)
llchange = 1;
@ -1937,7 +1962,13 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
* Record source link-layer address
* XXX is it dependent to ifp->if_type?
*/
if (lltable_try_set_entry_addr(ifp, ln, lladdr) == 0) {
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
linkhdr, &linkhdrsize, &lladdr_off) != 0)
return;
if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
lladdr_off) == 0) {
/* Entry was deleted */
return;
}
@ -2093,8 +2124,8 @@ nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
}
/*
* Do L2 address resolution for @sa_dst address. Stores found
* address in @desten buffer. Copy of lle ln_flags can be also
* Lookup link headerfor @sa_dst address. Stores found
* data in @desten buffer. Copy of lle ln_flags can be also
* saved in @pflags if @pflags is non-NULL.
*
* If destination LLE does not exists or lle state modification
@ -2144,7 +2175,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
ln = nd6_lookup(&dst6->sin6_addr, LLE_UNLOCKED, ifp);
if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) {
/* Entry found, let's copy lle info */
bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
bcopy(ln->r_linkdata, desten, ln->r_hdrlen);
if (pflags != NULL)
*pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR);
/* Check if we have feedback request from nd6 timer */
@ -2159,7 +2190,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
}
IF_AFDATA_RUNLOCK(ifp);
return (nd6_resolve_slow(ifp, m, dst6, desten, pflags));
return (nd6_resolve_slow(ifp, 0, m, dst6, desten, pflags));
}
@ -2175,12 +2206,13 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
* Set noinline to be dtrace-friendly
*/
static __noinline int
nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
nd6_resolve_slow(struct ifnet *ifp, int flags, struct mbuf *m,
const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
{
struct llentry *lle = NULL, *lle_tmp;
struct in6_addr *psrc, src;
int send_ns;
int send_ns, ll_len;
char *lladdr;
/*
* Address resolution or Neighbor Unreachability Detection
@ -2252,7 +2284,14 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
* send the packet.
*/
if (lle->ln_state > ND6_LLINFO_INCOMPLETE) {
bcopy(&lle->ll_addr, desten, ifp->if_addrlen);
if (flags & LLE_ADDRONLY) {
lladdr = lle->ll_addr;
ll_len = ifp->if_addrlen;
} else {
lladdr = lle->r_linkdata;
ll_len = lle->r_hdrlen;
}
bcopy(lladdr, desten, ll_len);
if (pflags != NULL)
*pflags = lle->la_flags;
LLE_WUNLOCK(lle);
@ -2312,6 +2351,27 @@ nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
return (EWOULDBLOCK);
}
/*
* Do L2 address resolution for @sa_dst address. Stores found
* address in @desten buffer. Copy of lle ln_flags can be also
* saved in @pflags if @pflags is non-NULL.
*
* Return values:
* - 0 on success (address copied to buffer).
* - EWOULDBLOCK (no local error, but address is still unresolved)
* - other errors (alloc failure, etc)
*/
int
nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
char *desten, uint32_t *pflags)
{
int error;
flags |= LLE_ADDRONLY;
error = nd6_resolve_slow(ifp, flags, NULL,
(const struct sockaddr_in6 *)dst, desten, pflags);
return (error);
}
int
nd6_flush_holdchain(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain,

View File

@ -410,6 +410,8 @@ void nd6_setmtu(struct ifnet *);
void nd6_llinfo_setstate(struct llentry *lle, int newstate);
void nd6_timer(void *);
void nd6_purge(struct ifnet *);
int nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst,
char *desten, uint32_t *pflags);
int nd6_resolve(struct ifnet *, int, struct mbuf *,
const struct sockaddr *, u_char *, uint32_t *);
int nd6_ioctl(u_long, caddr_t, struct ifnet *);

View File

@ -643,6 +643,9 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
union nd_opts ndopts;
struct mbuf *chain = NULL;
struct sockaddr_in6 sin6;
u_char linkhdr[LLE_MAX_LINKHDR];
size_t linkhdrsize;
int lladdr_off;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
if (ip6->ip6_hlim != 255) {
@ -765,7 +768,13 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
/*
* Record link-layer address, and update the state.
*/
if (lltable_try_set_entry_addr(ifp, ln, lladdr) == 0) {
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
linkhdr, &linkhdrsize, &lladdr_off) != 0)
return;
if (lltable_try_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
lladdr_off) == 0) {
ln = NULL;
goto freeit;
}
@ -792,7 +801,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
llchange = 0;
else {
if (ln->la_flags & LLE_VALID) {
if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
if (bcmp(lladdr, ln->ll_addr, ifp->if_addrlen))
llchange = 1;
else
llchange = 0;
@ -834,9 +843,12 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* Update link-local address, if any.
*/
if (lladdr != NULL) {
int ret;
ret = lltable_try_set_entry_addr(ifp, ln,lladdr);
if (ret == 0) {
linkhdrsize = sizeof(linkhdr);
if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
linkhdr, &linkhdrsize, &lladdr_off) != 0)
goto freeit;
if (lltable_try_set_entry_addr(ifp, ln, linkhdr,
linkhdrsize, lladdr_off) == 0) {
ln = NULL;
goto freeit;
}

View File

@ -1257,15 +1257,15 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, struct route *ro)
{
u_char edst[INFINIBAND_ALEN];
#if defined(INET) || defined(INET6)
struct llentry *lle = NULL;
#endif
struct rtentry *rt0 = NULL;
struct ipoib_header *eh;
int error = 0, is_gw = 0;
short type;
if (ro != NULL) {
if (!(m->m_flags & (M_BCAST | M_MCAST)))
lle = ro->ro_lle;
rt0 = ro->ro_rt;
if (rt0 != NULL && (rt0->rt_flags & RTF_GATEWAY) != 0)
is_gw = 1;
@ -1291,7 +1291,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
#ifdef INET
case AF_INET:
if (lle != NULL && (lle->la_flags & LLE_VALID))
memcpy(edst, &lle->ll_addr.mac8, sizeof(edst));
memcpy(edst, lle->ll_addr, sizeof(edst));
else if (m->m_flags & M_MCAST)
ip_ib_mc_map(((struct sockaddr_in *)dst)->sin_addr.s_addr, ifp->if_broadcastaddr, edst);
else
@ -1329,7 +1329,7 @@ ipoib_output(struct ifnet *ifp, struct mbuf *m,
#ifdef INET6
case AF_INET6:
if (lle != NULL && (lle->la_flags & LLE_VALID))
memcpy(edst, &lle->ll_addr.mac8, sizeof(edst));
memcpy(edst, lle->ll_addr, sizeof(edst));
else if (m->m_flags & M_MCAST)
ipv6_ib_mc_map(&((struct sockaddr_in6 *)dst)->sin6_addr, ifp->if_broadcastaddr, edst);
else

View File

@ -14,6 +14,11 @@
* 29 May 1998
*/
#ifndef _SKIPJACK_H_
#define _SKIPJACK_H_
extern void skipjack_forwards(u_int8_t *plain, u_int8_t *cipher, u_int8_t **key);
extern void skipjack_backwards(u_int8_t *cipher, u_int8_t *plain, u_int8_t **key);
extern void subkey_table_gen(u_int8_t *key, u_int8_t **key_tables);
#endif

View File

@ -75,196 +75,9 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform.h>
static int null_setkey(u_int8_t **, u_int8_t *, int);
static int des1_setkey(u_int8_t **, u_int8_t *, int);
static int des3_setkey(u_int8_t **, u_int8_t *, int);
static int blf_setkey(u_int8_t **, u_int8_t *, int);
static int cast5_setkey(u_int8_t **, u_int8_t *, int);
static int skipjack_setkey(u_int8_t **, u_int8_t *, int);
static int rijndael128_setkey(u_int8_t **, u_int8_t *, int);
static int aes_icm_setkey(u_int8_t **, u_int8_t *, int);
static int aes_xts_setkey(u_int8_t **, u_int8_t *, int);
static int cml_setkey(u_int8_t **, u_int8_t *, int);
static void null_encrypt(caddr_t, u_int8_t *);
static void des1_encrypt(caddr_t, u_int8_t *);
static void des3_encrypt(caddr_t, u_int8_t *);
static void blf_encrypt(caddr_t, u_int8_t *);
static void cast5_encrypt(caddr_t, u_int8_t *);
static void skipjack_encrypt(caddr_t, u_int8_t *);
static void rijndael128_encrypt(caddr_t, u_int8_t *);
static void aes_xts_encrypt(caddr_t, u_int8_t *);
static void cml_encrypt(caddr_t, u_int8_t *);
static void null_decrypt(caddr_t, u_int8_t *);
static void des1_decrypt(caddr_t, u_int8_t *);
static void des3_decrypt(caddr_t, u_int8_t *);
static void blf_decrypt(caddr_t, u_int8_t *);
static void cast5_decrypt(caddr_t, u_int8_t *);
static void skipjack_decrypt(caddr_t, u_int8_t *);
static void rijndael128_decrypt(caddr_t, u_int8_t *);
static void aes_xts_decrypt(caddr_t, u_int8_t *);
static void cml_decrypt(caddr_t, u_int8_t *);
static void aes_icm_crypt(caddr_t, u_int8_t *);
static void null_zerokey(u_int8_t **);
static void des1_zerokey(u_int8_t **);
static void des3_zerokey(u_int8_t **);
static void blf_zerokey(u_int8_t **);
static void cast5_zerokey(u_int8_t **);
static void skipjack_zerokey(u_int8_t **);
static void rijndael128_zerokey(u_int8_t **);
static void aes_icm_zerokey(u_int8_t **);
static void aes_xts_zerokey(u_int8_t **);
static void cml_zerokey(u_int8_t **);
static void aes_icm_reinit(caddr_t, u_int8_t *);
static void aes_xts_reinit(caddr_t, u_int8_t *);
static void aes_gcm_reinit(caddr_t, u_int8_t *);
static void null_init(void *);
static void null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len);
static int null_update(void *, const u_int8_t *, u_int16_t);
static void null_final(u_int8_t *, void *);
static int MD5Update_int(void *, const u_int8_t *, u_int16_t);
static void SHA1Init_int(void *);
static int SHA1Update_int(void *, const u_int8_t *, u_int16_t);
static void SHA1Final_int(u_int8_t *, void *);
static int RMD160Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA256Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA384Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
static u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **);
static u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **);
#define AESICM_BLOCKSIZE AES_BLOCK_LEN
struct aes_icm_ctx {
u_int32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)];
/* ac_block is initalized to IV */
u_int8_t ac_block[AESICM_BLOCKSIZE];
int ac_nr;
};
MALLOC_DEFINE(M_XDATA, "xform", "xform data buffers");
/* Encryption instances */
struct enc_xform enc_xform_null = {
CRYPTO_NULL_CBC, "NULL",
/* NB: blocksize of 4 is to generate a properly aligned ESP header */
NULL_BLOCK_LEN, 0, NULL_MIN_KEY, NULL_MAX_KEY,
null_encrypt,
null_decrypt,
null_setkey,
null_zerokey,
NULL,
};
struct enc_xform enc_xform_des = {
CRYPTO_DES_CBC, "DES",
DES_BLOCK_LEN, DES_BLOCK_LEN, DES_MIN_KEY, DES_MAX_KEY,
des1_encrypt,
des1_decrypt,
des1_setkey,
des1_zerokey,
NULL,
};
struct enc_xform enc_xform_3des = {
CRYPTO_3DES_CBC, "3DES",
DES3_BLOCK_LEN, DES3_BLOCK_LEN, TRIPLE_DES_MIN_KEY,
TRIPLE_DES_MAX_KEY,
des3_encrypt,
des3_decrypt,
des3_setkey,
des3_zerokey,
NULL,
};
struct enc_xform enc_xform_blf = {
CRYPTO_BLF_CBC, "Blowfish",
BLOWFISH_BLOCK_LEN, BLOWFISH_BLOCK_LEN, BLOWFISH_MIN_KEY,
BLOWFISH_MAX_KEY,
blf_encrypt,
blf_decrypt,
blf_setkey,
blf_zerokey,
NULL,
};
struct enc_xform enc_xform_cast5 = {
CRYPTO_CAST_CBC, "CAST-128",
CAST128_BLOCK_LEN, CAST128_BLOCK_LEN, CAST_MIN_KEY, CAST_MAX_KEY,
cast5_encrypt,
cast5_decrypt,
cast5_setkey,
cast5_zerokey,
NULL,
};
struct enc_xform enc_xform_skipjack = {
CRYPTO_SKIPJACK_CBC, "Skipjack",
SKIPJACK_BLOCK_LEN, SKIPJACK_BLOCK_LEN, SKIPJACK_MIN_KEY,
SKIPJACK_MAX_KEY,
skipjack_encrypt,
skipjack_decrypt, skipjack_setkey,
skipjack_zerokey,
NULL,
};
struct enc_xform enc_xform_rijndael128 = {
CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES",
RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, RIJNDAEL_MIN_KEY,
RIJNDAEL_MAX_KEY,
rijndael128_encrypt,
rijndael128_decrypt,
rijndael128_setkey,
rijndael128_zerokey,
NULL,
};
struct enc_xform enc_xform_aes_icm = {
CRYPTO_AES_ICM, "AES-ICM",
AES_BLOCK_LEN, AES_BLOCK_LEN, AES_MIN_KEY, AES_MAX_KEY,
aes_icm_crypt,
aes_icm_crypt,
aes_icm_setkey,
rijndael128_zerokey,
aes_icm_reinit,
};
struct enc_xform enc_xform_aes_nist_gcm = {
CRYPTO_AES_NIST_GCM_16, "AES-GCM",
AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY,
aes_icm_crypt,
aes_icm_crypt,
aes_icm_setkey,
aes_icm_zerokey,
aes_gcm_reinit,
};
struct enc_xform enc_xform_aes_nist_gmac = {
CRYPTO_AES_NIST_GMAC, "AES-GMAC",
AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY,
NULL,
NULL,
NULL,
NULL,
NULL,
};
struct enc_xform enc_xform_aes_xts = {
CRYPTO_AES_XTS, "AES-XTS",
AES_BLOCK_LEN, AES_XTS_IV_LEN, AES_XTS_MIN_KEY, AES_XTS_MAX_KEY,
aes_xts_encrypt,
aes_xts_decrypt,
aes_xts_setkey,
aes_xts_zerokey,
aes_xts_reinit
};
struct enc_xform enc_xform_arc4 = {
CRYPTO_ARC4, "ARC4",
ARC4_BLOCK_LEN, ARC4_IV_LEN, ARC4_MIN_KEY, ARC4_MAX_KEY,
@ -275,711 +88,26 @@ struct enc_xform enc_xform_arc4 = {
NULL,
};
struct enc_xform enc_xform_camellia = {
CRYPTO_CAMELLIA_CBC, "Camellia",
CAMELLIA_BLOCK_LEN, CAMELLIA_BLOCK_LEN, CAMELLIA_MIN_KEY,
CAMELLIA_MAX_KEY,
cml_encrypt,
cml_decrypt,
cml_setkey,
cml_zerokey,
NULL,
};
/* Authentication instances */
struct auth_hash auth_hash_null = { /* NB: context isn't used */
CRYPTO_NULL_HMAC, "NULL-HMAC",
NULL_HMAC_KEY_LEN, NULL_HASH_LEN, sizeof(int), NULL_HMAC_BLOCK_LEN,
null_init, null_reinit, null_reinit, null_update, null_final
};
/* Include the encryption algorithms */
#include "xform_null.c"
#include "xform_des1.c"
#include "xform_des3.c"
#include "xform_blf.c"
#include "xform_cast5.c"
#include "xform_skipjack.c"
#include "xform_rijndael.c"
#include "xform_aes_icm.c"
#include "xform_aes_xts.c"
#include "xform_cml.c"
/* Include the authentication and hashing algorithms */
#include "xform_gmac.c"
#include "xform_md5.c"
#include "xform_rmd160.c"
#include "xform_sha1.c"
#include "xform_sha2.c"
/* Include the compression algorithms */
#include "xform_deflate.c"
struct auth_hash auth_hash_hmac_md5 = {
CRYPTO_MD5_HMAC, "HMAC-MD5",
MD5_HMAC_KEY_LEN, MD5_HASH_LEN, sizeof(MD5_CTX), MD5_HMAC_BLOCK_LEN,
(void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int,
(void (*) (u_int8_t *, void *)) MD5Final
};
struct auth_hash auth_hash_hmac_sha1 = {
CRYPTO_SHA1_HMAC, "HMAC-SHA1",
SHA1_HMAC_KEY_LEN, SHA1_HASH_LEN, sizeof(SHA1_CTX), SHA1_HMAC_BLOCK_LEN,
SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
};
struct auth_hash auth_hash_hmac_ripemd_160 = {
CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
RIPEMD160_HMAC_KEY_LEN, RIPEMD160_HASH_LEN, sizeof(RMD160_CTX),
RIPEMD160_HMAC_BLOCK_LEN,
(void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int,
(void (*)(u_int8_t *, void *)) RMD160Final
};
struct auth_hash auth_hash_key_md5 = {
CRYPTO_MD5_KPDK, "Keyed MD5",
NULL_HMAC_KEY_LEN, MD5_KPDK_HASH_LEN, sizeof(MD5_CTX), 0,
(void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int,
(void (*)(u_int8_t *, void *)) MD5Final
};
struct auth_hash auth_hash_key_sha1 = {
CRYPTO_SHA1_KPDK, "Keyed SHA1",
NULL_HMAC_KEY_LEN, SHA1_KPDK_HASH_LEN, sizeof(SHA1_CTX), 0,
SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
};
struct auth_hash auth_hash_hmac_sha2_256 = {
CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
SHA2_256_HMAC_KEY_LEN, SHA2_256_HASH_LEN, sizeof(SHA256_CTX),
SHA2_256_HMAC_BLOCK_LEN,
(void (*)(void *)) SHA256_Init, NULL, NULL, SHA256Update_int,
(void (*)(u_int8_t *, void *)) SHA256_Final
};
struct auth_hash auth_hash_hmac_sha2_384 = {
CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384",
SHA2_384_HMAC_KEY_LEN, SHA2_384_HASH_LEN, sizeof(SHA384_CTX),
SHA2_384_HMAC_BLOCK_LEN,
(void (*)(void *)) SHA384_Init, NULL, NULL, SHA384Update_int,
(void (*)(u_int8_t *, void *)) SHA384_Final
};
struct auth_hash auth_hash_hmac_sha2_512 = {
CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512",
SHA2_512_HMAC_KEY_LEN, SHA2_512_HASH_LEN, sizeof(SHA512_CTX),
SHA2_512_HMAC_BLOCK_LEN,
(void (*)(void *)) SHA512_Init, NULL, NULL, SHA512Update_int,
(void (*)(u_int8_t *, void *)) SHA512_Final
};
struct auth_hash auth_hash_nist_gmac_aes_128 = {
CRYPTO_AES_128_NIST_GMAC, "GMAC-AES-128",
AES_128_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
(int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
(void (*)(u_int8_t *, void *)) AES_GMAC_Final
};
struct auth_hash auth_hash_nist_gmac_aes_192 = {
CRYPTO_AES_192_NIST_GMAC, "GMAC-AES-192",
AES_192_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
(int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
(void (*)(u_int8_t *, void *)) AES_GMAC_Final
};
struct auth_hash auth_hash_nist_gmac_aes_256 = {
CRYPTO_AES_256_NIST_GMAC, "GMAC-AES-256",
AES_256_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
(int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
(void (*)(u_int8_t *, void *)) AES_GMAC_Final
};
/* Compression instance */
struct comp_algo comp_algo_deflate = {
CRYPTO_DEFLATE_COMP, "Deflate",
90, deflate_compress,
deflate_decompress
};
/*
* Encryption wrapper routines.
*/
static void
null_encrypt(caddr_t key, u_int8_t *blk)
{
}
static void
null_decrypt(caddr_t key, u_int8_t *blk)
{
}
static int
null_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
*sched = NULL;
return 0;
}
static void
null_zerokey(u_int8_t **sched)
{
*sched = NULL;
}
static void
des1_encrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb_encrypt(cb, cb, p[0], DES_ENCRYPT);
}
static void
des1_decrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb_encrypt(cb, cb, p[0], DES_DECRYPT);
}
static int
des1_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
des_key_schedule *p;
int err;
p = malloc(sizeof (des_key_schedule),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (p != NULL) {
des_set_key((des_cblock *) key, p[0]);
err = 0;
} else
err = ENOMEM;
*sched = (u_int8_t *) p;
return err;
}
static void
des1_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof (des_key_schedule));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
static void
des3_encrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_ENCRYPT);
}
static void
des3_decrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_DECRYPT);
}
static int
des3_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
des_key_schedule *p;
int err;
p = malloc(3*sizeof (des_key_schedule),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (p != NULL) {
des_set_key((des_cblock *)(key + 0), p[0]);
des_set_key((des_cblock *)(key + 8), p[1]);
des_set_key((des_cblock *)(key + 16), p[2]);
err = 0;
} else
err = ENOMEM;
*sched = (u_int8_t *) p;
return err;
}
static void
des3_zerokey(u_int8_t **sched)
{
bzero(*sched, 3*sizeof (des_key_schedule));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
static void
blf_encrypt(caddr_t key, u_int8_t *blk)
{
BF_LONG t[2];
memcpy(t, blk, sizeof (t));
t[0] = ntohl(t[0]);
t[1] = ntohl(t[1]);
/* NB: BF_encrypt expects the block in host order! */
BF_encrypt(t, (BF_KEY *) key);
t[0] = htonl(t[0]);
t[1] = htonl(t[1]);
memcpy(blk, t, sizeof (t));
}
static void
blf_decrypt(caddr_t key, u_int8_t *blk)
{
BF_LONG t[2];
memcpy(t, blk, sizeof (t));
t[0] = ntohl(t[0]);
t[1] = ntohl(t[1]);
/* NB: BF_decrypt expects the block in host order! */
BF_decrypt(t, (BF_KEY *) key);
t[0] = htonl(t[0]);
t[1] = htonl(t[1]);
memcpy(blk, t, sizeof (t));
}
static int
blf_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
*sched = malloc(sizeof(BF_KEY),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*sched != NULL) {
BF_set_key((BF_KEY *) *sched, len, key);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
blf_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(BF_KEY));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
static void
cast5_encrypt(caddr_t key, u_int8_t *blk)
{
cast_encrypt((cast_key *) key, blk, blk);
}
static void
cast5_decrypt(caddr_t key, u_int8_t *blk)
{
cast_decrypt((cast_key *) key, blk, blk);
}
static int
cast5_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
*sched = malloc(sizeof(cast_key), M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*sched != NULL) {
cast_setkey((cast_key *)*sched, key, len);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
cast5_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(cast_key));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
static void
skipjack_encrypt(caddr_t key, u_int8_t *blk)
{
skipjack_forwards(blk, blk, (u_int8_t **) key);
}
static void
skipjack_decrypt(caddr_t key, u_int8_t *blk)
{
skipjack_backwards(blk, blk, (u_int8_t **) key);
}
static int
skipjack_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
/* NB: allocate all the memory that's needed at once */
*sched = malloc(10 * (sizeof(u_int8_t *) + 0x100),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*sched != NULL) {
u_int8_t** key_tables = (u_int8_t**) *sched;
u_int8_t* table = (u_int8_t*) &key_tables[10];
int k;
for (k = 0; k < 10; k++) {
key_tables[k] = table;
table += 0x100;
}
subkey_table_gen(key, (u_int8_t **) *sched);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
skipjack_zerokey(u_int8_t **sched)
{
bzero(*sched, 10 * (sizeof(u_int8_t *) + 0x100));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
static void
rijndael128_encrypt(caddr_t key, u_int8_t *blk)
{
rijndael_encrypt((rijndael_ctx *) key, (u_char *) blk, (u_char *) blk);
}
static void
rijndael128_decrypt(caddr_t key, u_int8_t *blk)
{
rijndael_decrypt(((rijndael_ctx *) key), (u_char *) blk,
(u_char *) blk);
}
static int
rijndael128_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
if (len != 16 && len != 24 && len != 32)
return (EINVAL);
*sched = malloc(sizeof(rijndael_ctx), M_CRYPTO_DATA,
M_NOWAIT|M_ZERO);
if (*sched != NULL) {
rijndael_set_key((rijndael_ctx *) *sched, (u_char *) key,
len * 8);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
rijndael128_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(rijndael_ctx));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
void
aes_icm_reinit(caddr_t key, u_int8_t *iv)
{
struct aes_icm_ctx *ctx;
ctx = (struct aes_icm_ctx *)key;
bcopy(iv, ctx->ac_block, AESICM_BLOCKSIZE);
}
void
aes_gcm_reinit(caddr_t key, u_int8_t *iv)
{
struct aes_icm_ctx *ctx;
aes_icm_reinit(key, iv);
ctx = (struct aes_icm_ctx *)key;
/* GCM starts with 2 as counter 1 is used for final xor of tag. */
bzero(&ctx->ac_block[AESICM_BLOCKSIZE - 4], 4);
ctx->ac_block[AESICM_BLOCKSIZE - 1] = 2;
}
void
aes_icm_crypt(caddr_t key, u_int8_t *data)
{
struct aes_icm_ctx *ctx;
u_int8_t keystream[AESICM_BLOCKSIZE];
int i;
ctx = (struct aes_icm_ctx *)key;
rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream);
for (i = 0; i < AESICM_BLOCKSIZE; i++)
data[i] ^= keystream[i];
explicit_bzero(keystream, sizeof(keystream));
/* increment counter */
for (i = AESICM_BLOCKSIZE - 1;
i >= 0; i--)
if (++ctx->ac_block[i]) /* continue on overflow */
break;
}
int
aes_icm_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
struct aes_icm_ctx *ctx;
if (len != 16 && len != 24 && len != 32)
return EINVAL;
*sched = malloc(sizeof(struct aes_icm_ctx), M_CRYPTO_DATA,
M_NOWAIT | M_ZERO);
if (*sched == NULL)
return ENOMEM;
ctx = (struct aes_icm_ctx *)*sched;
ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key, len * 8);
return 0;
}
void
aes_icm_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(struct aes_icm_ctx));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
#define AES_XTS_BLOCKSIZE 16
#define AES_XTS_IVSIZE 8
#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */
struct aes_xts_ctx {
rijndael_ctx key1;
rijndael_ctx key2;
u_int8_t tweak[AES_XTS_BLOCKSIZE];
};
void
aes_xts_reinit(caddr_t key, u_int8_t *iv)
{
struct aes_xts_ctx *ctx = (struct aes_xts_ctx *)key;
u_int64_t blocknum;
u_int i;
/*
* Prepare tweak as E_k2(IV). IV is specified as LE representation
* of a 64-bit block number which we allow to be passed in directly.
*/
bcopy(iv, &blocknum, AES_XTS_IVSIZE);
for (i = 0; i < AES_XTS_IVSIZE; i++) {
ctx->tweak[i] = blocknum & 0xff;
blocknum >>= 8;
}
/* Last 64 bits of IV are always zero */
bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE);
rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak);
}
static void
aes_xts_crypt(struct aes_xts_ctx *ctx, u_int8_t *data, u_int do_encrypt)
{
u_int8_t block[AES_XTS_BLOCKSIZE];
u_int i, carry_in, carry_out;
for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
block[i] = data[i] ^ ctx->tweak[i];
if (do_encrypt)
rijndael_encrypt(&ctx->key1, block, data);
else
rijndael_decrypt(&ctx->key1, block, data);
for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
data[i] ^= ctx->tweak[i];
/* Exponentiate tweak */
carry_in = 0;
for (i = 0; i < AES_XTS_BLOCKSIZE; i++) {
carry_out = ctx->tweak[i] & 0x80;
ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0);
carry_in = carry_out;
}
if (carry_in)
ctx->tweak[0] ^= AES_XTS_ALPHA;
bzero(block, sizeof(block));
}
void
aes_xts_encrypt(caddr_t key, u_int8_t *data)
{
aes_xts_crypt((struct aes_xts_ctx *)key, data, 1);
}
void
aes_xts_decrypt(caddr_t key, u_int8_t *data)
{
aes_xts_crypt((struct aes_xts_ctx *)key, data, 0);
}
int
aes_xts_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
struct aes_xts_ctx *ctx;
if (len != 32 && len != 64)
return EINVAL;
*sched = malloc(sizeof(struct aes_xts_ctx), M_CRYPTO_DATA,
M_NOWAIT | M_ZERO);
if (*sched == NULL)
return ENOMEM;
ctx = (struct aes_xts_ctx *)*sched;
rijndael_set_key(&ctx->key1, key, len * 4);
rijndael_set_key(&ctx->key2, key + (len / 2), len * 4);
return 0;
}
void
aes_xts_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(struct aes_xts_ctx));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
static void
cml_encrypt(caddr_t key, u_int8_t *blk)
{
camellia_encrypt((camellia_ctx *) key, (u_char *) blk, (u_char *) blk);
}
static void
cml_decrypt(caddr_t key, u_int8_t *blk)
{
camellia_decrypt(((camellia_ctx *) key), (u_char *) blk,
(u_char *) blk);
}
static int
cml_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
if (len != 16 && len != 24 && len != 32)
return (EINVAL);
*sched = malloc(sizeof(camellia_ctx), M_CRYPTO_DATA,
M_NOWAIT|M_ZERO);
if (*sched != NULL) {
camellia_set_key((camellia_ctx *) *sched, (u_char *) key,
len * 8);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
cml_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(camellia_ctx));
free(*sched, M_CRYPTO_DATA);
*sched = NULL;
}
/*
* And now for auth.
*/
static void
null_init(void *ctx)
{
}
static void
null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len)
{
}
static int
null_update(void *ctx, const u_int8_t *buf, u_int16_t len)
{
return 0;
}
static void
null_final(u_int8_t *buf, void *ctx)
{
if (buf != (u_int8_t *) 0)
bzero(buf, 12);
}
static int
RMD160Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
RMD160Update(ctx, buf, len);
return 0;
}
static int
MD5Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
MD5Update(ctx, buf, len);
return 0;
}
static void
SHA1Init_int(void *ctx)
{
SHA1Init(ctx);
}
static int
SHA1Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA1Update(ctx, buf, len);
return 0;
}
static void
SHA1Final_int(u_int8_t *blk, void *ctx)
{
SHA1Final(blk, ctx);
}
static int
SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA256_Update(ctx, buf, len);
return 0;
}
static int
SHA384Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA384_Update(ctx, buf, len);
return 0;
}
static int
SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA512_Update(ctx, buf, len);
return 0;
}
/*
* And compression
*/
static u_int32_t
deflate_compress(data, size, out)
u_int8_t *data;
u_int32_t size;
u_int8_t **out;
{
return deflate_global(data, size, 0, out);
}
static u_int32_t
deflate_decompress(data, size, out)
u_int8_t *data;
u_int32_t size;
u_int8_t **out;
{
return deflate_global(data, size, 1, out);
}

View File

@ -39,83 +39,9 @@
#include <opencrypto/rmd160.h>
#include <opencrypto/gmac.h>
/* Declarations */
struct auth_hash {
int type;
char *name;
u_int16_t keysize;
u_int16_t hashsize;
u_int16_t ctxsize;
u_int16_t blocksize;
void (*Init) (void *);
void (*Setkey) (void *, const u_int8_t *, u_int16_t);
void (*Reinit) (void *, const u_int8_t *, u_int16_t);
int (*Update) (void *, const u_int8_t *, u_int16_t);
void (*Final) (u_int8_t *, void *);
};
/* XXX use a define common with other hash stuff ! */
#define AH_ALEN_MAX 64 /* max authenticator hash length */
struct enc_xform {
int type;
char *name;
u_int16_t blocksize;
u_int16_t ivsize;
u_int16_t minkey, maxkey;
void (*encrypt) (caddr_t, u_int8_t *);
void (*decrypt) (caddr_t, u_int8_t *);
int (*setkey) (u_int8_t **, u_int8_t *, int len);
void (*zerokey) (u_int8_t **);
void (*reinit) (caddr_t, u_int8_t *);
};
struct comp_algo {
int type;
char *name;
size_t minlen;
u_int32_t (*compress) (u_int8_t *, u_int32_t, u_int8_t **);
u_int32_t (*decompress) (u_int8_t *, u_int32_t, u_int8_t **);
};
union authctx {
MD5_CTX md5ctx;
SHA1_CTX sha1ctx;
RMD160_CTX rmd160ctx;
SHA256_CTX sha256ctx;
SHA384_CTX sha384ctx;
SHA512_CTX sha512ctx;
struct aes_gmac_ctx aes_gmac_ctx;
};
extern struct enc_xform enc_xform_null;
extern struct enc_xform enc_xform_des;
extern struct enc_xform enc_xform_3des;
extern struct enc_xform enc_xform_blf;
extern struct enc_xform enc_xform_cast5;
extern struct enc_xform enc_xform_skipjack;
extern struct enc_xform enc_xform_rijndael128;
extern struct enc_xform enc_xform_aes_icm;
extern struct enc_xform enc_xform_aes_nist_gcm;
extern struct enc_xform enc_xform_aes_nist_gmac;
extern struct enc_xform enc_xform_aes_xts;
extern struct enc_xform enc_xform_arc4;
extern struct enc_xform enc_xform_camellia;
extern struct auth_hash auth_hash_null;
extern struct auth_hash auth_hash_key_md5;
extern struct auth_hash auth_hash_key_sha1;
extern struct auth_hash auth_hash_hmac_md5;
extern struct auth_hash auth_hash_hmac_sha1;
extern struct auth_hash auth_hash_hmac_ripemd_160;
extern struct auth_hash auth_hash_hmac_sha2_256;
extern struct auth_hash auth_hash_hmac_sha2_384;
extern struct auth_hash auth_hash_hmac_sha2_512;
extern struct auth_hash auth_hash_nist_gmac_aes_128;
extern struct auth_hash auth_hash_nist_gmac_aes_192;
extern struct auth_hash auth_hash_nist_gmac_aes_256;
extern struct comp_algo comp_algo_deflate;
#include <opencrypto/xform_auth.h>
#include <opencrypto/xform_comp.h>
#include <opencrypto/xform_enc.h>
#ifdef _KERNEL
#include <sys/malloc.h>

View File

@ -0,0 +1,152 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/xform_enc.h>
static int aes_icm_setkey(u_int8_t **, u_int8_t *, int);
static void aes_icm_crypt(caddr_t, u_int8_t *);
static void aes_icm_zerokey(u_int8_t **);
static void aes_icm_reinit(caddr_t, u_int8_t *);
static void aes_gcm_reinit(caddr_t, u_int8_t *);
/* Encryption instances */
struct enc_xform enc_xform_aes_icm = {
CRYPTO_AES_ICM, "AES-ICM",
AES_BLOCK_LEN, AES_BLOCK_LEN, AES_MIN_KEY, AES_MAX_KEY,
aes_icm_crypt,
aes_icm_crypt,
aes_icm_setkey,
rijndael128_zerokey,
aes_icm_reinit,
};
struct enc_xform enc_xform_aes_nist_gcm = {
CRYPTO_AES_NIST_GCM_16, "AES-GCM",
AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY,
aes_icm_crypt,
aes_icm_crypt,
aes_icm_setkey,
aes_icm_zerokey,
aes_gcm_reinit,
};
/*
* Encryption wrapper routines.
*/
static void
aes_icm_reinit(caddr_t key, u_int8_t *iv)
{
struct aes_icm_ctx *ctx;
ctx = (struct aes_icm_ctx *)key;
bcopy(iv, ctx->ac_block, AESICM_BLOCKSIZE);
}
static void
aes_gcm_reinit(caddr_t key, u_int8_t *iv)
{
struct aes_icm_ctx *ctx;
aes_icm_reinit(key, iv);
ctx = (struct aes_icm_ctx *)key;
/* GCM starts with 2 as counter 1 is used for final xor of tag. */
bzero(&ctx->ac_block[AESICM_BLOCKSIZE - 4], 4);
ctx->ac_block[AESICM_BLOCKSIZE - 1] = 2;
}
static void
aes_icm_crypt(caddr_t key, u_int8_t *data)
{
struct aes_icm_ctx *ctx;
u_int8_t keystream[AESICM_BLOCKSIZE];
int i;
ctx = (struct aes_icm_ctx *)key;
rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream);
for (i = 0; i < AESICM_BLOCKSIZE; i++)
data[i] ^= keystream[i];
explicit_bzero(keystream, sizeof(keystream));
/* increment counter */
for (i = AESICM_BLOCKSIZE - 1;
i >= 0; i--)
if (++ctx->ac_block[i]) /* continue on overflow */
break;
}
static int
aes_icm_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
struct aes_icm_ctx *ctx;
if (len != 16 && len != 24 && len != 32)
return EINVAL;
*sched = KMALLOC(sizeof(struct aes_icm_ctx), M_CRYPTO_DATA,
M_NOWAIT | M_ZERO);
if (*sched == NULL)
return ENOMEM;
ctx = (struct aes_icm_ctx *)*sched;
ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key, len * 8);
return 0;
}
static void
aes_icm_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(struct aes_icm_ctx));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,164 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/xform_enc.h>
static int aes_xts_setkey(u_int8_t **, u_int8_t *, int);
static void aes_xts_encrypt(caddr_t, u_int8_t *);
static void aes_xts_decrypt(caddr_t, u_int8_t *);
static void aes_xts_zerokey(u_int8_t **);
static void aes_xts_reinit(caddr_t, u_int8_t *);
/* Encryption instances */
struct enc_xform enc_xform_aes_xts = {
CRYPTO_AES_XTS, "AES-XTS",
AES_BLOCK_LEN, AES_XTS_IV_LEN, AES_XTS_MIN_KEY, AES_XTS_MAX_KEY,
aes_xts_encrypt,
aes_xts_decrypt,
aes_xts_setkey,
aes_xts_zerokey,
aes_xts_reinit
};
/*
* Encryption wrapper routines.
*/
static void
aes_xts_reinit(caddr_t key, u_int8_t *iv)
{
struct aes_xts_ctx *ctx = (struct aes_xts_ctx *)key;
u_int64_t blocknum;
u_int i;
/*
* Prepare tweak as E_k2(IV). IV is specified as LE representation
* of a 64-bit block number which we allow to be passed in directly.
*/
bcopy(iv, &blocknum, AES_XTS_IVSIZE);
for (i = 0; i < AES_XTS_IVSIZE; i++) {
ctx->tweak[i] = blocknum & 0xff;
blocknum >>= 8;
}
/* Last 64 bits of IV are always zero */
bzero(ctx->tweak + AES_XTS_IVSIZE, AES_XTS_IVSIZE);
rijndael_encrypt(&ctx->key2, ctx->tweak, ctx->tweak);
}
static void
aes_xts_crypt(struct aes_xts_ctx *ctx, u_int8_t *data, u_int do_encrypt)
{
u_int8_t block[AES_XTS_BLOCKSIZE];
u_int i, carry_in, carry_out;
for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
block[i] = data[i] ^ ctx->tweak[i];
if (do_encrypt)
rijndael_encrypt(&ctx->key1, block, data);
else
rijndael_decrypt(&ctx->key1, block, data);
for (i = 0; i < AES_XTS_BLOCKSIZE; i++)
data[i] ^= ctx->tweak[i];
/* Exponentiate tweak */
carry_in = 0;
for (i = 0; i < AES_XTS_BLOCKSIZE; i++) {
carry_out = ctx->tweak[i] & 0x80;
ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0);
carry_in = carry_out;
}
if (carry_in)
ctx->tweak[0] ^= AES_XTS_ALPHA;
bzero(block, sizeof(block));
}
static void
aes_xts_encrypt(caddr_t key, u_int8_t *data)
{
aes_xts_crypt((struct aes_xts_ctx *)key, data, 1);
}
static void
aes_xts_decrypt(caddr_t key, u_int8_t *data)
{
aes_xts_crypt((struct aes_xts_ctx *)key, data, 0);
}
static int
aes_xts_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
struct aes_xts_ctx *ctx;
if (len != 32 && len != 64)
return EINVAL;
*sched = KMALLOC(sizeof(struct aes_xts_ctx), M_CRYPTO_DATA,
M_NOWAIT | M_ZERO);
if (*sched == NULL)
return ENOMEM;
ctx = (struct aes_xts_ctx *)*sched;
rijndael_set_key(&ctx->key1, key, len * 4);
rijndael_set_key(&ctx->key2, key + (len / 2), len * 4);
return 0;
}
static void
aes_xts_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(struct aes_xts_ctx));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,89 @@
/* $FreeBSD$ */
/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */
/*-
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
* This code was written by Angelos D. Keromytis in Athens, Greece, in
* February 2000. Network Security Technologies Inc. (NSTI) kindly
* supported the development of this code.
*
* Copyright (c) 2000 Angelos D. Keromytis
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software without fee
* is hereby granted, provided that this entire notice is included in
* all source code copies of any software which is or includes a copy or
* modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#ifndef _CRYPTO_XFORM_AUTH_H_
#define _CRYPTO_XFORM_AUTH_H_
#include <sys/malloc.h>
#include <sys/errno.h>
#include <sys/md5.h>
#include <crypto/sha1.h>
#include <crypto/sha2/sha256.h>
#include <crypto/sha2/sha384.h>
#include <crypto/sha2/sha512.h>
#include <opencrypto/rmd160.h>
#include <opencrypto/gmac.h>
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform_userland.h>
/* XXX use a define common with other hash stuff ! */
#define AH_ALEN_MAX 64 /* max authenticator hash length */
/* Declarations */
struct auth_hash {
int type;
char *name;
u_int16_t keysize;
u_int16_t hashsize;
u_int16_t ctxsize;
u_int16_t blocksize;
void (*Init) (void *);
void (*Setkey) (void *, const u_int8_t *, u_int16_t);
void (*Reinit) (void *, const u_int8_t *, u_int16_t);
int (*Update) (void *, const u_int8_t *, u_int16_t);
void (*Final) (u_int8_t *, void *);
};
extern struct auth_hash auth_hash_null;
extern struct auth_hash auth_hash_key_md5;
extern struct auth_hash auth_hash_key_sha1;
extern struct auth_hash auth_hash_hmac_md5;
extern struct auth_hash auth_hash_hmac_sha1;
extern struct auth_hash auth_hash_hmac_ripemd_160;
extern struct auth_hash auth_hash_hmac_sha2_256;
extern struct auth_hash auth_hash_hmac_sha2_384;
extern struct auth_hash auth_hash_hmac_sha2_512;
extern struct auth_hash auth_hash_nist_gmac_aes_128;
extern struct auth_hash auth_hash_nist_gmac_aes_192;
extern struct auth_hash auth_hash_nist_gmac_aes_256;
union authctx {
MD5_CTX md5ctx;
SHA1_CTX sha1ctx;
RMD160_CTX rmd160ctx;
SHA256_CTX sha256ctx;
SHA384_CTX sha384ctx;
SHA512_CTX sha512ctx;
struct aes_gmac_ctx aes_gmac_ctx;
};
#endif /* _CRYPTO_XFORM_AUTH_H_ */

127
sys/opencrypto/xform_blf.c Normal file
View File

@ -0,0 +1,127 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/blowfish/blowfish.h>
#include <opencrypto/xform_enc.h>
static int blf_setkey(u_int8_t **, u_int8_t *, int);
static void blf_encrypt(caddr_t, u_int8_t *);
static void blf_decrypt(caddr_t, u_int8_t *);
static void blf_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_blf = {
CRYPTO_BLF_CBC, "Blowfish",
BLOWFISH_BLOCK_LEN, BLOWFISH_BLOCK_LEN, BLOWFISH_MIN_KEY,
BLOWFISH_MAX_KEY,
blf_encrypt,
blf_decrypt,
blf_setkey,
blf_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
blf_encrypt(caddr_t key, u_int8_t *blk)
{
BF_LONG t[2];
memcpy(t, blk, sizeof (t));
t[0] = ntohl(t[0]);
t[1] = ntohl(t[1]);
/* NB: BF_encrypt expects the block in host order! */
BF_encrypt(t, (BF_KEY *) key);
t[0] = htonl(t[0]);
t[1] = htonl(t[1]);
memcpy(blk, t, sizeof (t));
}
static void
blf_decrypt(caddr_t key, u_int8_t *blk)
{
BF_LONG t[2];
memcpy(t, blk, sizeof (t));
t[0] = ntohl(t[0]);
t[1] = ntohl(t[1]);
/* NB: BF_decrypt expects the block in host order! */
BF_decrypt(t, (BF_KEY *) key);
t[0] = htonl(t[0]);
t[1] = htonl(t[1]);
memcpy(blk, t, sizeof (t));
}
static int
blf_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
*sched = KMALLOC(sizeof(BF_KEY),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*sched != NULL) {
BF_set_key((BF_KEY *) *sched, len, key);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
blf_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(BF_KEY));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,107 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/cast.h>
#include <opencrypto/xform_enc.h>
static int cast5_setkey(u_int8_t **, u_int8_t *, int);
static void cast5_encrypt(caddr_t, u_int8_t *);
static void cast5_decrypt(caddr_t, u_int8_t *);
static void cast5_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_cast5 = {
CRYPTO_CAST_CBC, "CAST-128",
CAST128_BLOCK_LEN, CAST128_BLOCK_LEN, CAST_MIN_KEY, CAST_MAX_KEY,
cast5_encrypt,
cast5_decrypt,
cast5_setkey,
cast5_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
cast5_encrypt(caddr_t key, u_int8_t *blk)
{
cast_encrypt((cast_key *) key, blk, blk);
}
static void
cast5_decrypt(caddr_t key, u_int8_t *blk)
{
cast_decrypt((cast_key *) key, blk, blk);
}
static int
cast5_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
*sched = KMALLOC(sizeof(cast_key), M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*sched != NULL) {
cast_setkey((cast_key *)*sched, key, len);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
cast5_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(cast_key));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

113
sys/opencrypto/xform_cml.c Normal file
View File

@ -0,0 +1,113 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/camellia/camellia.h>
#include <opencrypto/xform_enc.h>
static int cml_setkey(u_int8_t **, u_int8_t *, int);
static void cml_encrypt(caddr_t, u_int8_t *);
static void cml_decrypt(caddr_t, u_int8_t *);
static void cml_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_camellia = {
CRYPTO_CAMELLIA_CBC, "Camellia",
CAMELLIA_BLOCK_LEN, CAMELLIA_BLOCK_LEN, CAMELLIA_MIN_KEY,
CAMELLIA_MAX_KEY,
cml_encrypt,
cml_decrypt,
cml_setkey,
cml_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
cml_encrypt(caddr_t key, u_int8_t *blk)
{
camellia_encrypt((camellia_ctx *) key, (u_char *) blk, (u_char *) blk);
}
static void
cml_decrypt(caddr_t key, u_int8_t *blk)
{
camellia_decrypt(((camellia_ctx *) key), (u_char *) blk,
(u_char *) blk);
}
static int
cml_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
if (len != 16 && len != 24 && len != 32)
return (EINVAL);
*sched = KMALLOC(sizeof(camellia_ctx), M_CRYPTO_DATA,
M_NOWAIT|M_ZERO);
if (*sched != NULL) {
camellia_set_key((camellia_ctx *) *sched, (u_char *) key,
len * 8);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
cml_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(camellia_ctx));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,52 @@
/* $FreeBSD$ */
/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */
/*-
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
* This code was written by Angelos D. Keromytis in Athens, Greece, in
* February 2000. Network Security Technologies Inc. (NSTI) kindly
* supported the development of this code.
*
* Copyright (c) 2000 Angelos D. Keromytis
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software without fee
* is hereby granted, provided that this entire notice is included in
* all source code copies of any software which is or includes a copy or
* modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#ifndef _CRYPTO_XFORM_COMP_H_
#define _CRYPTO_XFORM_COMP_H_
#include <sys/malloc.h>
#include <sys/errno.h>
#include <opencrypto/deflate.h>
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform_userland.h>
/* Declarations */
struct comp_algo {
int type;
char *name;
size_t minlen;
u_int32_t (*compress) (u_int8_t *, u_int32_t, u_int8_t **);
u_int32_t (*decompress) (u_int8_t *, u_int32_t, u_int8_t **);
};
extern struct comp_algo comp_algo_deflate;
#endif /* _CRYPTO_XFORM_COMP_H_ */

View File

@ -0,0 +1,86 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/deflate.h>
#include <opencrypto/xform_comp.h>
static u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **);
static u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **);
/* Compression instance */
struct comp_algo comp_algo_deflate = {
CRYPTO_DEFLATE_COMP, "Deflate",
90, deflate_compress,
deflate_decompress
};
/*
* And compression
*/
static u_int32_t
deflate_compress(data, size, out)
u_int8_t *data;
u_int32_t size;
u_int8_t **out;
{
return deflate_global(data, size, 0, out);
}
static u_int32_t
deflate_decompress(data, size, out)
u_int8_t *data;
u_int32_t size;
u_int8_t **out;
{
return deflate_global(data, size, 1, out);
}

116
sys/opencrypto/xform_des1.c Normal file
View File

@ -0,0 +1,116 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/des/des.h>
#include <opencrypto/xform_enc.h>
static int des1_setkey(u_int8_t **, u_int8_t *, int);
static void des1_encrypt(caddr_t, u_int8_t *);
static void des1_decrypt(caddr_t, u_int8_t *);
static void des1_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_des = {
CRYPTO_DES_CBC, "DES",
DES_BLOCK_LEN, DES_BLOCK_LEN, DES_MIN_KEY, DES_MAX_KEY,
des1_encrypt,
des1_decrypt,
des1_setkey,
des1_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
des1_encrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb_encrypt(cb, cb, p[0], DES_ENCRYPT);
}
static void
des1_decrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb_encrypt(cb, cb, p[0], DES_DECRYPT);
}
static int
des1_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
des_key_schedule *p;
int err;
p = KMALLOC(sizeof (des_key_schedule),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (p != NULL) {
des_set_key((des_cblock *) key, p[0]);
err = 0;
} else
err = ENOMEM;
*sched = (u_int8_t *) p;
return err;
}
static void
des1_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof (des_key_schedule));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

119
sys/opencrypto/xform_des3.c Normal file
View File

@ -0,0 +1,119 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/des/des.h>
#include <opencrypto/xform_enc.h>
static int des3_setkey(u_int8_t **, u_int8_t *, int);
static void des3_encrypt(caddr_t, u_int8_t *);
static void des3_decrypt(caddr_t, u_int8_t *);
static void des3_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_3des = {
CRYPTO_3DES_CBC, "3DES",
DES3_BLOCK_LEN, DES3_BLOCK_LEN, TRIPLE_DES_MIN_KEY,
TRIPLE_DES_MAX_KEY,
des3_encrypt,
des3_decrypt,
des3_setkey,
des3_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
des3_encrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_ENCRYPT);
}
static void
des3_decrypt(caddr_t key, u_int8_t *blk)
{
des_cblock *cb = (des_cblock *) blk;
des_key_schedule *p = (des_key_schedule *) key;
des_ecb3_encrypt(cb, cb, p[0], p[1], p[2], DES_DECRYPT);
}
static int
des3_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
des_key_schedule *p;
int err;
p = KMALLOC(3*sizeof (des_key_schedule),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (p != NULL) {
des_set_key((des_cblock *)(key + 0), p[0]);
des_set_key((des_cblock *)(key + 8), p[1]);
des_set_key((des_cblock *)(key + 16), p[2]);
err = 0;
} else
err = ENOMEM;
*sched = (u_int8_t *) p;
return err;
}
static void
des3_zerokey(u_int8_t **sched)
{
bzero(*sched, 3*sizeof (des_key_schedule));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,92 @@
/* $FreeBSD$ */
/* $OpenBSD: xform.h,v 1.8 2001/08/28 12:20:43 ben Exp $ */
/*-
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
*
* This code was written by Angelos D. Keromytis in Athens, Greece, in
* February 2000. Network Security Technologies Inc. (NSTI) kindly
* supported the development of this code.
*
* Copyright (c) 2000 Angelos D. Keromytis
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software without fee
* is hereby granted, provided that this entire notice is included in
* all source code copies of any software which is or includes a copy or
* modification of this software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#ifndef _CRYPTO_XFORM_ENC_H_
#define _CRYPTO_XFORM_ENC_H_
#include <sys/malloc.h>
#include <sys/errno.h>
#include <crypto/blowfish/blowfish.h>
#include <crypto/des/des.h>
#include <crypto/rijndael/rijndael.h>
#include <crypto/camellia/camellia.h>
#include <opencrypto/cast.h>
#include <opencrypto/skipjack.h>
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform_userland.h>
#define AESICM_BLOCKSIZE AES_BLOCK_LEN
#define AES_XTS_BLOCKSIZE 16
#define AES_XTS_IVSIZE 8
#define AES_XTS_ALPHA 0x87 /* GF(2^128) generator polynomial */
/* Declarations */
struct enc_xform {
int type;
char *name;
u_int16_t blocksize;
u_int16_t ivsize;
u_int16_t minkey, maxkey;
void (*encrypt) (caddr_t, u_int8_t *);
void (*decrypt) (caddr_t, u_int8_t *);
int (*setkey) (u_int8_t **, u_int8_t *, int len);
void (*zerokey) (u_int8_t **);
void (*reinit) (caddr_t, u_int8_t *);
};
extern struct enc_xform enc_xform_null;
extern struct enc_xform enc_xform_des;
extern struct enc_xform enc_xform_3des;
extern struct enc_xform enc_xform_blf;
extern struct enc_xform enc_xform_cast5;
extern struct enc_xform enc_xform_skipjack;
extern struct enc_xform enc_xform_rijndael128;
extern struct enc_xform enc_xform_aes_icm;
extern struct enc_xform enc_xform_aes_nist_gcm;
extern struct enc_xform enc_xform_aes_nist_gmac;
extern struct enc_xform enc_xform_aes_xts;
extern struct enc_xform enc_xform_arc4;
extern struct enc_xform enc_xform_camellia;
struct aes_icm_ctx {
u_int32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)];
/* ac_block is initalized to IV */
u_int8_t ac_block[AESICM_BLOCKSIZE];
int ac_nr;
};
struct aes_xts_ctx {
rijndael_ctx key1;
rijndael_ctx key2;
u_int8_t tweak[AES_XTS_BLOCKSIZE];
};
#endif /* _CRYPTO_XFORM_ENC_H_ */

View File

@ -0,0 +1,99 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/gmac.h>
#include <opencrypto/xform_auth.h>
/* Encryption instances */
struct enc_xform enc_xform_aes_nist_gmac = {
CRYPTO_AES_NIST_GMAC, "AES-GMAC",
AES_ICM_BLOCK_LEN, AES_GCM_IV_LEN, AES_MIN_KEY, AES_MAX_KEY,
NULL,
NULL,
NULL,
NULL,
NULL,
};
/* Authentication instances */
struct auth_hash auth_hash_nist_gmac_aes_128 = {
CRYPTO_AES_128_NIST_GMAC, "GMAC-AES-128",
AES_128_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
(int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
(void (*)(u_int8_t *, void *)) AES_GMAC_Final
};
struct auth_hash auth_hash_nist_gmac_aes_192 = {
CRYPTO_AES_192_NIST_GMAC, "GMAC-AES-192",
AES_192_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
(int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
(void (*)(u_int8_t *, void *)) AES_GMAC_Final
};
struct auth_hash auth_hash_nist_gmac_aes_256 = {
CRYPTO_AES_256_NIST_GMAC, "GMAC-AES-256",
AES_256_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Reinit,
(int (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Update,
(void (*)(u_int8_t *, void *)) AES_GMAC_Final
};

View File

@ -0,0 +1,81 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/md5.h>
#include <opencrypto/xform_auth.h>
static int MD5Update_int(void *, const u_int8_t *, u_int16_t);
/* Authentication instances */
struct auth_hash auth_hash_hmac_md5 = {
CRYPTO_MD5_HMAC, "HMAC-MD5",
MD5_HMAC_KEY_LEN, MD5_HASH_LEN, sizeof(MD5_CTX), MD5_HMAC_BLOCK_LEN,
(void (*) (void *)) MD5Init, NULL, NULL, MD5Update_int,
(void (*) (u_int8_t *, void *)) MD5Final
};
struct auth_hash auth_hash_key_md5 = {
CRYPTO_MD5_KPDK, "Keyed MD5",
NULL_HMAC_KEY_LEN, MD5_KPDK_HASH_LEN, sizeof(MD5_CTX), 0,
(void (*)(void *)) MD5Init, NULL, NULL, MD5Update_int,
(void (*)(u_int8_t *, void *)) MD5Final
};
/*
* And now for auth.
*/
static int
MD5Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
MD5Update(ctx, buf, len);
return 0;
}

136
sys/opencrypto/xform_null.c Normal file
View File

@ -0,0 +1,136 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/xform_auth.h>
#include <opencrypto/xform_enc.h>
static int null_setkey(u_int8_t **, u_int8_t *, int);
static void null_encrypt(caddr_t, u_int8_t *);
static void null_decrypt(caddr_t, u_int8_t *);
static void null_zerokey(u_int8_t **);
static void null_init(void *);
static void null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len);
static int null_update(void *, const u_int8_t *, u_int16_t);
static void null_final(u_int8_t *, void *);
/* Encryption instances */
struct enc_xform enc_xform_null = {
CRYPTO_NULL_CBC, "NULL",
/* NB: blocksize of 4 is to generate a properly aligned ESP header */
NULL_BLOCK_LEN, 0, NULL_MIN_KEY, NULL_MAX_KEY,
null_encrypt,
null_decrypt,
null_setkey,
null_zerokey,
NULL,
};
/* Authentication instances */
struct auth_hash auth_hash_null = { /* NB: context isn't used */
CRYPTO_NULL_HMAC, "NULL-HMAC",
NULL_HMAC_KEY_LEN, NULL_HASH_LEN, sizeof(int), NULL_HMAC_BLOCK_LEN,
null_init, null_reinit, null_reinit, null_update, null_final
};
/*
* Encryption wrapper routines.
*/
static void
null_encrypt(caddr_t key, u_int8_t *blk)
{
}
static void
null_decrypt(caddr_t key, u_int8_t *blk)
{
}
static int
null_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
*sched = NULL;
return 0;
}
static void
null_zerokey(u_int8_t **sched)
{
*sched = NULL;
}
/*
* And now for auth.
*/
static void
null_init(void *ctx)
{
}
static void
null_reinit(void *ctx, const u_int8_t *buf, u_int16_t len)
{
}
static int
null_update(void *ctx, const u_int8_t *buf, u_int16_t len)
{
return 0;
}
static void
null_final(u_int8_t *buf, void *ctx)
{
if (buf != (u_int8_t *) 0)
bzero(buf, 12);
}

View File

@ -0,0 +1,113 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/rijndael/rijndael.h>
#include <opencrypto/xform_enc.h>
static int rijndael128_setkey(u_int8_t **, u_int8_t *, int);
static void rijndael128_encrypt(caddr_t, u_int8_t *);
static void rijndael128_decrypt(caddr_t, u_int8_t *);
static void rijndael128_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_rijndael128 = {
CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES",
RIJNDAEL128_BLOCK_LEN, RIJNDAEL128_BLOCK_LEN, RIJNDAEL_MIN_KEY,
RIJNDAEL_MAX_KEY,
rijndael128_encrypt,
rijndael128_decrypt,
rijndael128_setkey,
rijndael128_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
rijndael128_encrypt(caddr_t key, u_int8_t *blk)
{
rijndael_encrypt((rijndael_ctx *) key, (u_char *) blk, (u_char *) blk);
}
static void
rijndael128_decrypt(caddr_t key, u_int8_t *blk)
{
rijndael_decrypt(((rijndael_ctx *) key), (u_char *) blk,
(u_char *) blk);
}
static int
rijndael128_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
if (len != 16 && len != 24 && len != 32)
return (EINVAL);
*sched = KMALLOC(sizeof(rijndael_ctx), M_CRYPTO_DATA,
M_NOWAIT|M_ZERO);
if (*sched != NULL) {
rijndael_set_key((rijndael_ctx *) *sched, (u_char *) key,
len * 8);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
rijndael128_zerokey(u_int8_t **sched)
{
bzero(*sched, sizeof(rijndael_ctx));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,75 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/rmd160.h>
#include <opencrypto/xform_auth.h>
static int RMD160Update_int(void *, const u_int8_t *, u_int16_t);
/* Authentication instances */
struct auth_hash auth_hash_hmac_ripemd_160 = {
CRYPTO_RIPEMD160_HMAC, "HMAC-RIPEMD-160",
RIPEMD160_HMAC_KEY_LEN, RIPEMD160_HASH_LEN, sizeof(RMD160_CTX),
RIPEMD160_HMAC_BLOCK_LEN,
(void (*)(void *)) RMD160Init, NULL, NULL, RMD160Update_int,
(void (*)(u_int8_t *, void *)) RMD160Final
};
/*
* And now for auth.
*/
static int
RMD160Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
RMD160Update(ctx, buf, len);
return 0;
}

View File

@ -0,0 +1,93 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/sha1.h>
#include <opencrypto/xform_auth.h>
static void SHA1Init_int(void *);
static int SHA1Update_int(void *, const u_int8_t *, u_int16_t);
static void SHA1Final_int(u_int8_t *, void *);
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha1 = {
CRYPTO_SHA1_HMAC, "HMAC-SHA1",
SHA1_HMAC_KEY_LEN, SHA1_HASH_LEN, sizeof(SHA1_CTX), SHA1_HMAC_BLOCK_LEN,
SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
};
struct auth_hash auth_hash_key_sha1 = {
CRYPTO_SHA1_KPDK, "Keyed SHA1",
NULL_HMAC_KEY_LEN, SHA1_KPDK_HASH_LEN, sizeof(SHA1_CTX), 0,
SHA1Init_int, NULL, NULL, SHA1Update_int, SHA1Final_int
};
/*
* And now for auth.
*/
static void
SHA1Init_int(void *ctx)
{
SHA1Init(ctx);
}
static int
SHA1Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA1Update(ctx, buf, len);
return 0;
}
static void
SHA1Final_int(u_int8_t *blk, void *ctx)
{
SHA1Final(blk, ctx);
}

109
sys/opencrypto/xform_sha2.c Normal file
View File

@ -0,0 +1,109 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <crypto/sha2/sha256.h>
#include <crypto/sha2/sha384.h>
#include <crypto/sha2/sha512.h>
#include <opencrypto/xform_auth.h>
static int SHA256Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA384Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha2_256 = {
CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
SHA2_256_HMAC_KEY_LEN, SHA2_256_HASH_LEN, sizeof(SHA256_CTX),
SHA2_256_HMAC_BLOCK_LEN,
(void (*)(void *)) SHA256_Init, NULL, NULL, SHA256Update_int,
(void (*)(u_int8_t *, void *)) SHA256_Final
};
struct auth_hash auth_hash_hmac_sha2_384 = {
CRYPTO_SHA2_384_HMAC, "HMAC-SHA2-384",
SHA2_384_HMAC_KEY_LEN, SHA2_384_HASH_LEN, sizeof(SHA384_CTX),
SHA2_384_HMAC_BLOCK_LEN,
(void (*)(void *)) SHA384_Init, NULL, NULL, SHA384Update_int,
(void (*)(u_int8_t *, void *)) SHA384_Final
};
struct auth_hash auth_hash_hmac_sha2_512 = {
CRYPTO_SHA2_512_HMAC, "HMAC-SHA2-512",
SHA2_512_HMAC_KEY_LEN, SHA2_512_HASH_LEN, sizeof(SHA512_CTX),
SHA2_512_HMAC_BLOCK_LEN,
(void (*)(void *)) SHA512_Init, NULL, NULL, SHA512Update_int,
(void (*)(u_int8_t *, void *)) SHA512_Final
};
/*
* And now for auth.
*/
static int
SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA256_Update(ctx, buf, len);
return 0;
}
static int
SHA384Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA384_Update(ctx, buf, len);
return 0;
}
static int
SHA512Update_int(void *ctx, const u_int8_t *buf, u_int16_t len)
{
SHA512_Update(ctx, buf, len);
return 0;
}

View File

@ -0,0 +1,117 @@
/* $OpenBSD: xform.c,v 1.16 2001/08/28 12:20:43 ben Exp $ */
/*-
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr),
* Niels Provos (provos@physnet.uni-hamburg.de) and
* Damien Miller (djm@mindrot.org).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Additional features in 1999 by Angelos D. Keromytis.
*
* AES XTS implementation in 2008 by Damien Miller
*
* Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
* Angelos D. Keromytis and Niels Provos.
*
* Copyright (C) 2001, Angelos D. Keromytis.
*
* Copyright (C) 2008, Damien Miller
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by John-Mark Gurney
* under sponsorship of the FreeBSD Foundation and
* Rubicon Communications, LLC (Netgate).
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <opencrypto/skipjack.h>
#include <opencrypto/xform_enc.h>
static int skipjack_setkey(u_int8_t **, u_int8_t *, int);
static void skipjack_encrypt(caddr_t, u_int8_t *);
static void skipjack_decrypt(caddr_t, u_int8_t *);
static void skipjack_zerokey(u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_skipjack = {
CRYPTO_SKIPJACK_CBC, "Skipjack",
SKIPJACK_BLOCK_LEN, SKIPJACK_BLOCK_LEN, SKIPJACK_MIN_KEY,
SKIPJACK_MAX_KEY,
skipjack_encrypt,
skipjack_decrypt, skipjack_setkey,
skipjack_zerokey,
NULL,
};
/*
* Encryption wrapper routines.
*/
static void
skipjack_encrypt(caddr_t key, u_int8_t *blk)
{
skipjack_forwards(blk, blk, (u_int8_t **) key);
}
static void
skipjack_decrypt(caddr_t key, u_int8_t *blk)
{
skipjack_backwards(blk, blk, (u_int8_t **) key);
}
static int
skipjack_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
int err;
/* NB: allocate all the memory that's needed at once */
*sched = KMALLOC(10 * (sizeof(u_int8_t *) + 0x100),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*sched != NULL) {
u_int8_t** key_tables = (u_int8_t**) *sched;
u_int8_t* table = (u_int8_t*) &key_tables[10];
int k;
for (k = 0; k < 10; k++) {
key_tables[k] = table;
table += 0x100;
}
subkey_table_gen(key, (u_int8_t **) *sched);
err = 0;
} else
err = ENOMEM;
return err;
}
static void
skipjack_zerokey(u_int8_t **sched)
{
bzero(*sched, 10 * (sizeof(u_int8_t *) + 0x100));
KFREE(*sched, M_CRYPTO_DATA);
*sched = NULL;
}

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE 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.
*
* $FreeBSD$
*/
#ifndef _CRYPTO_XFORM_USERLAND_H_
#define _CRYPTO_XFORM_USERLAND_H_
#ifdef _KERNEL
#include <sys/systm.h>
#define KMALLOC(size, type, flags) malloc(size, type, flags)
#define KFREE(ptr, type) free(ptr, type)
#else /* not _KERNEL */
#ifdef _STAND
#include <stand.h>
#else /* !_STAND */
#include <stdlib.h>
#include <string.h>
#endif /* _STAND */
#define KMALLOC(size, type, flags) malloc(size)
#define KFREE(ptr, type) free(ptr)
#endif /* _KERNEL */
#endif /* _CRYPTO_XFORM_USERLAND_H_ */

View File

@ -316,8 +316,20 @@ booke_init(uint32_t arg1, uint32_t arg2)
ret = powerpc_init(dtbp, 0, 0, mdp);
/* Enable L1 caches */
/* Default to 32 byte cache line size. */
switch ((mfpvr()) >> 16) {
case FSL_E500mc:
case FSL_E5500:
case FSL_E6500:
cacheline_size = 64;
break;
}
/* Enable caches */
booke_enable_l1_cache();
booke_enable_l2_cache();
booke_enable_bpred();
return (ret);
}

View File

@ -301,7 +301,7 @@ bp_ntlb1s:
.globl bp_tlb1
bp_tlb1:
.space 4 * 3 * 16
.space 4 * 3 * 64
.globl bp_tlb1_end
bp_tlb1_end:
@ -657,77 +657,6 @@ __boot_page_padding:
/* locore subroutines */
/************************************************************************/
/*
* void tid_flush(tlbtid_t tid);
*
* Invalidate all TLB0 entries which match the given TID. Note this is
* dedicated for cases when invalidation(s) should NOT be propagated to other
* CPUs.
*
* void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way);
*
* XXX: why isn't this in C?
*/
ENTRY(tid_flush)
cmpwi %r3, TID_KERNEL
beq tid_flush_end /* don't evict kernel translations */
/* Disable interrupts */
mfmsr %r10
wrteei 0
li %r6, 0 /* ways counter */
loop_ways:
li %r7, 0 /* entries [per way] counter */
loop_entries:
/* Select TLB0 and ESEL (way) */
lis %r8, MAS0_TLBSEL0@h
rlwimi %r8, %r6, 16, 14, 15
mtspr SPR_MAS0, %r8
isync
/* Select EPN (entry within the way) */
rlwinm %r8, %r7, 12, 13, 19
mtspr SPR_MAS2, %r8
isync
tlbre
/* Check if valid entry */
mfspr %r8, SPR_MAS1
andis. %r9, %r8, MAS1_VALID@h
beq next_entry /* invalid entry */
/* Check if this is our TID */
rlwinm %r9, %r8, 16, 24, 31
cmplw %r9, %r3
bne next_entry /* not our TID */
/* Clear VALID bit */
rlwinm %r8, %r8, 0, 1, 31
mtspr SPR_MAS1, %r8
isync
tlbwe
isync
msync
next_entry:
addi %r7, %r7, 1
cmpw %r7, %r5
bne loop_entries
/* Next way */
addi %r6, %r6, 1
cmpw %r6, %r4
bne loop_ways
/* Restore MSR (possibly re-enable interrupts) */
mtmsr %r10
isync
tid_flush_end:
blr
/*
* Cache disable/enable/inval sequences according
* to section 2.16 of E500CORE RM.
@ -801,6 +730,113 @@ ENTRY(icache_enable)
isync
blr
/*
* L2 cache disable/enable/inval sequences for E500mc.
*/
ENTRY(l2cache_inval)
mfspr %r3, SPR_L2CSR0
oris %r3, %r3, (L2CSR0_L2FI | L2CSR0_L2LFC)@h
ori %r3, %r3, (L2CSR0_L2FI | L2CSR0_L2LFC)@l
isync
mtspr SPR_L2CSR0, %r3
isync
1: mfspr %r3, SPR_L2CSR0
andis. %r3, %r3, L2CSR0_L2FI@h
bne 1b
blr
ENTRY(l2cache_enable)
mfspr %r3, SPR_L2CSR0
oris %r3, %r3, (L2CSR0_L2E | L2CSR0_L2PE)@h
isync
mtspr SPR_L2CSR0, %r3
isync
blr
/*
* Branch predictor setup.
*/
ENTRY(bpred_enable)
mfspr %r3, SPR_BUCSR
ori %r3, %r3, BUCSR_BBFI
isync
mtspr SPR_BUCSR, %r3
isync
ori %r3, %r3, BUCSR_BPEN
isync
mtspr SPR_BUCSR, %r3
isync
blr
ENTRY(dataloss_erratum_access)
/* Lock two cache lines into I-Cache */
sync
mfspr %r11, SPR_L1CSR1
rlwinm %r11, %r11, 0, ~L1CSR1_ICUL
sync
isync
mtspr SPR_L1CSR1, %r11
isync
mflr %r9
bl 1f
.long 2f-.
1:
mflr %r5
lwz %r8, 0(%r5)
mtlr %r9
add %r8, %r8, %r5
icbtls 0, 0, %r8
addi %r9, %r8, 64
sync
mfspr %r11, SPR_L1CSR1
3: andi. %r11, %r11, L1CSR1_ICUL
bne 3b
icbtls 0, 0, %r9
sync
mfspr %r11, SPR_L1CSR1
3: andi. %r11, %r11, L1CSR1_ICUL
bne 3b
b 2f
.align 6
/* Inside a locked cacheline, wait a while, write, then wait a while */
2: sync
mfspr %r5, TBR_TBL
4: addis %r11, %r5, 0x100000@h /* wait around one million timebase ticks */
mfspr %r5, TBR_TBL
subf. %r5, %r5, %r11
bgt 4b
stw %r4, 0(%r3)
mfspr %r5, TBR_TBL
4: addis %r11, %r5, 0x100000@h /* wait around one million timebase ticks */
mfspr %r5, TBR_TBL
subf. %r5, %r5, %r11
bgt 4b
sync
/*
* Fill out the rest of this cache line and the next with nops,
* to ensure that nothing outside the locked area will be
* fetched due to a branch.
*/
.rept 19
nop
.endr
icblc 0, 0, %r8
icblc 0, 0, %r9
blr
/*
* int setfault()
*

View File

@ -27,9 +27,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/machdep.h>
#include <dev/fdt/fdt_common.h>
@ -42,6 +48,7 @@ extern void icache_enable(void);
extern void icache_inval(void);
extern void l2cache_enable(void);
extern void l2cache_inval(void);
extern void bpred_enable(void);
void
booke_init_tlb(vm_paddr_t fdt_immr_pa)
@ -79,7 +86,6 @@ booke_enable_l1_cache(void)
(csr & L1CSR1_ICE) ? "en" : "dis");
}
#if 0
void
booke_enable_l2_cache(void)
{
@ -102,55 +108,18 @@ booke_enable_l2_cache(void)
}
void
booke_enable_l3_cache(void)
booke_enable_bpred(void)
{
uint32_t csr, size, ver;
uint32_t csr;
/* Enable L3 CoreNet Platform Cache (CPC) */
ver = SVR_VER(mfspr(SPR_SVR));
if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 ||
ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) {
csr = ccsr_read4(OCP85XX_CPC_CSR0);
if ((csr & OCP85XX_CPC_CSR0_CE) == 0) {
l3cache_inval();
l3cache_enable();
}
csr = ccsr_read4(OCP85XX_CPC_CSR0);
if ((boothowto & RB_VERBOSE) != 0 ||
(csr & OCP85XX_CPC_CSR0_CE) == 0) {
size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0));
printf("L3 Corenet Platform Cache: %d KB %sabled\n",
size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ?
"dis" : "en");
}
}
bpred_enable();
csr = mfspr(SPR_BUCSR);
if ((boothowto & RB_VERBOSE) != 0 || (csr & BUCSR_BPEN) == 0)
printf("Branch Predictor %sabled\n",
(csr & BUCSR_BPEN) ? "en" : "dis");
}
void
booke_disable_l2_cache(void)
{
}
static void
l3cache_inval(void)
{
/* Flash invalidate the CPC and clear all the locks */
ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI |
OCP85XX_CPC_CSR0_LFC);
while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI |
OCP85XX_CPC_CSR0_LFC))
;
}
static void
l3cache_enable(void)
{
ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE |
OCP85XX_CPC_CSR0_PE);
/* Read back to sync write */
ccsr_read4(OCP85XX_CPC_CSR0);
}
#endif

View File

@ -161,7 +161,6 @@ unsigned int kernel_ptbls; /* Number of KVA ptbls. */
#define PMAP_REMOVE_DONE(pmap) \
((pmap) != kernel_pmap && (pmap)->pm_stats.resident_count == 0)
extern void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way);
extern int elf32_nxstack;
/**************************************************************************/
@ -195,6 +194,7 @@ static unsigned int tlb1_idx;
static vm_offset_t tlb1_map_base = VM_MAX_KERNEL_ADDRESS;
static tlbtid_t tid_alloc(struct pmap *);
static void tid_flush(tlbtid_t tid);
static void tlb_print_entry(int, uint32_t, uint32_t, uint32_t, uint32_t);
@ -2235,8 +2235,17 @@ mmu_booke_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size)
static void
mmu_booke_zero_page(mmu_t mmu, vm_page_t m)
{
vm_offset_t off, va;
mmu_booke_zero_page_area(mmu, m, 0, PAGE_SIZE);
mtx_lock(&zero_page_mutex);
va = zero_page_va;
mmu_booke_kenter(mmu, va, VM_PAGE_TO_PHYS(m));
for (off = 0; off < PAGE_SIZE; off += cacheline_size)
__asm __volatile("dcbzl 0,%0" :: "r"(va + off));
mmu_booke_kremove(mmu, va);
mtx_unlock(&zero_page_mutex);
}
/*
@ -2915,7 +2924,7 @@ tid_alloc(pmap_t pmap)
tidbusy[thiscpu][tid]->pm_tid[thiscpu] = TID_NONE;
/* Flush all entries from TLB0 matching this TID. */
tid_flush(tid, tlb0_ways, tlb0_entries_per_way);
tid_flush(tid);
}
tidbusy[thiscpu][tid] = pmap;
@ -3426,3 +3435,48 @@ tlb1_iomapped(int i, vm_paddr_t pa, vm_size_t size, vm_offset_t *va)
*va = (tlb1[i].mas2 & MAS2_EPN_MASK) + (pa - pa_start);
return (0);
}
/*
* Invalidate all TLB0 entries which match the given TID. Note this is
* dedicated for cases when invalidations should NOT be propagated to other
* CPUs.
*/
static void
tid_flush(tlbtid_t tid)
{
register_t msr;
uint32_t mas0, mas1, mas2;
int entry, way;
/* Don't evict kernel translations */
if (tid == TID_KERNEL)
return;
msr = mfmsr();
__asm __volatile("wrteei 0");
for (way = 0; way < TLB0_WAYS; way++)
for (entry = 0; entry < TLB0_ENTRIES_PER_WAY; entry++) {
mas0 = MAS0_TLBSEL(0) | MAS0_ESEL(way);
mtspr(SPR_MAS0, mas0);
__asm __volatile("isync");
mas2 = entry << MAS2_TLB0_ENTRY_IDX_SHIFT;
mtspr(SPR_MAS2, mas2);
__asm __volatile("isync; tlbre");
mas1 = mfspr(SPR_MAS1);
if (!(mas1 & MAS1_VALID))
continue;
if (((mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT) != tid)
continue;
mas1 &= ~MAS1_VALID;
mtspr(SPR_MAS1, mas1);
__asm __volatile("isync; tlbwe; isync; msync");
}
mtmsr(msr);
}

View File

@ -32,18 +32,26 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/reboot.h>
#include <sys/rman.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/machdep.h>
#include <machine/pio.h>
#include <machine/spr.h>
#include <dev/fdt/fdt_common.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
#include <powerpc/mpc85xx/mpc85xx.h>
@ -249,3 +257,166 @@ law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
return (rv);
}
static void
l3cache_inval(void)
{
/* Flash invalidate the CPC and clear all the locks */
ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_FI |
OCP85XX_CPC_CSR0_LFC);
while (ccsr_read4(OCP85XX_CPC_CSR0) & (OCP85XX_CPC_CSR0_FI |
OCP85XX_CPC_CSR0_LFC))
;
}
static void
l3cache_enable(void)
{
ccsr_write4(OCP85XX_CPC_CSR0, OCP85XX_CPC_CSR0_CE |
OCP85XX_CPC_CSR0_PE);
/* Read back to sync write */
ccsr_read4(OCP85XX_CPC_CSR0);
}
void
mpc85xx_enable_l3_cache(void)
{
uint32_t csr, size, ver;
/* Enable L3 CoreNet Platform Cache (CPC) */
ver = SVR_VER(mfspr(SPR_SVR));
if (ver == SVR_P2041 || ver == SVR_P2041E || ver == SVR_P3041 ||
ver == SVR_P3041E || ver == SVR_P5020 || ver == SVR_P5020E) {
csr = ccsr_read4(OCP85XX_CPC_CSR0);
if ((csr & OCP85XX_CPC_CSR0_CE) == 0) {
l3cache_inval();
l3cache_enable();
}
csr = ccsr_read4(OCP85XX_CPC_CSR0);
if ((boothowto & RB_VERBOSE) != 0 ||
(csr & OCP85XX_CPC_CSR0_CE) == 0) {
size = OCP85XX_CPC_CFG0_SZ_K(ccsr_read4(OCP85XX_CPC_CFG0));
printf("L3 Corenet Platform Cache: %d KB %sabled\n",
size, (csr & OCP85XX_CPC_CSR0_CE) == 0 ?
"dis" : "en");
}
}
}
static void
mpc85xx_dataloss_erratum_spr976(void)
{
uint32_t svr = SVR_VER(mfspr(SPR_SVR));
/* Ignore whether it's the E variant */
svr &= ~0x8;
if (svr != SVR_P3041 && svr != SVR_P4040 &&
svr != SVR_P4080 && svr != SVR_P5020)
return;
mb();
isync();
mtspr(976, (mfspr(976) & ~0x1f8) | 0x48);
isync();
}
static vm_offset_t
mpc85xx_map_dcsr(void)
{
phandle_t node;
u_long b, s;
int err;
/*
* Try to access the dcsr node directly i.e. through /aliases/.
*/
if ((node = OF_finddevice("dcsr")) != -1)
if (fdt_is_compatible_strict(node, "fsl,dcsr"))
goto moveon;
/*
* Find the node the long way.
*/
if ((node = OF_finddevice("/")) == -1)
return (ENXIO);
if ((node = ofw_bus_find_compatible(node, "fsl,dcsr")) == 0)
return (ENXIO);
moveon:
err = fdt_get_range(node, 0, &b, &s);
if (err != 0)
return (err);
#ifdef QORIQ_DPAA
law_enable(OCP85XX_TGTIF_DCSR, b, 0x400000);
#endif
return pmap_early_io_map(b, 0x400000);
}
void
mpc85xx_fix_errata(vm_offset_t va_ccsr)
{
uint32_t svr = SVR_VER(mfspr(SPR_SVR));
vm_offset_t va_dcsr;
/* Ignore whether it's the E variant */
svr &= ~0x8;
if (svr != SVR_P3041 && svr != SVR_P4040 &&
svr != SVR_P4080 && svr != SVR_P5020)
return;
if (mfmsr() & PSL_EE)
return;
/*
* dcsr region need to be mapped thus patch can refer to.
* Align dcsr right after ccsbar.
*/
va_dcsr = mpc85xx_map_dcsr();
if (va_dcsr == 0)
goto err;
/*
* As A004510 errata specify, special purpose register 976
* SPR976[56:60] = 6'b001001 must be set. e500mc core reference manual
* does not document SPR976 register.
*/
mpc85xx_dataloss_erratum_spr976();
/*
* Specific settings in the CCF and core platform cache (CPC)
* are required to reconfigure the CoreNet coherency fabric.
* The register settings that should be updated are described
* in errata and relay on base address, offset and updated value.
* Special conditions must be used to update these registers correctly.
*/
dataloss_erratum_access(va_dcsr + 0xb0e08, 0xe0201800);
dataloss_erratum_access(va_dcsr + 0xb0e18, 0xe0201800);
dataloss_erratum_access(va_dcsr + 0xb0e38, 0xe0400000);
dataloss_erratum_access(va_dcsr + 0xb0008, 0x00900000);
dataloss_erratum_access(va_dcsr + 0xb0e40, 0xe00a0000);
switch (svr) {
case SVR_P5020:
dataloss_erratum_access(va_ccsr + 0x18600, 0xc0000000);
break;
case SVR_P4040:
case SVR_P4080:
dataloss_erratum_access(va_ccsr + 0x18600, 0xff000000);
break;
case SVR_P3041:
dataloss_erratum_access(va_ccsr + 0x18600, 0xf0000000);
}
dataloss_erratum_access(va_ccsr + 0x10f00, 0x415e5000);
dataloss_erratum_access(va_ccsr + 0x11f00, 0x415e5000);
err:
return;
}

Some files were not shown because too many files have changed in this diff Show More