mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-26 20:12:44 +00:00
Compare commits
52 Commits
a2a75b45b7
...
91d38d869a
Author | SHA1 | Date | |
---|---|---|---|
|
91d38d869a | ||
|
f2233ac33a | ||
|
9206c79961 | ||
|
6d77827b96 | ||
|
5317480967 | ||
|
6d4c59e261 | ||
|
2839ad58dd | ||
|
5ac39263d8 | ||
|
5bd08172b4 | ||
|
56b7685ae3 | ||
|
4cc5d081d8 | ||
|
cca0dc49e0 | ||
|
3abef90c32 | ||
|
c0a5ee953f | ||
|
ccb973da1f | ||
|
cab31f5633 | ||
|
5035db222e | ||
|
501c4801ed | ||
|
3a212cc66a | ||
|
73465bb47b | ||
|
37cef00192 | ||
|
e9fa399180 | ||
|
c7fa232e9b | ||
|
ccbe9a9f73 | ||
|
dfe57951f0 | ||
|
4ab2a84e09 | ||
|
bf06074106 | ||
|
370ad2d367 | ||
|
bde575b273 | ||
|
67218bcea8 | ||
|
31784ee1e3 | ||
|
af1ef35a00 | ||
|
b2f7c53430 | ||
|
67f9307907 | ||
|
8585680682 | ||
|
fb4cdd5160 | ||
|
c1e304c60c | ||
|
c94d6389e4 | ||
|
4d58cf6ff9 | ||
|
bef05a7537 | ||
|
aa308b49e3 | ||
|
73b42eff25 | ||
|
6ec4ff7088 | ||
|
2d6923790b | ||
|
aebac84982 | ||
|
78d6582411 | ||
|
c4b7af5304 | ||
|
1a1cec19da | ||
|
2d3b870df0 | ||
|
f74bdc3752 | ||
|
caaceed159 | ||
|
7bcd510a7b |
5
RELNOTES
5
RELNOTES
@ -10,6 +10,11 @@ newline. Entries should be separated by a newline.
|
||||
|
||||
Changes to this file should not be MFCed.
|
||||
|
||||
b2f7c53430c3:
|
||||
Kernel TLS is now enabled by default in kernels including KTLS
|
||||
support. KTLS is included in GENERIC kernels for aarch64,
|
||||
amd64, powerpc64, and powerpc64le.
|
||||
|
||||
f57efe95cc25:
|
||||
New mididump(1) utility which dumps MIDI 1.0 events in real time.
|
||||
|
||||
|
@ -505,6 +505,8 @@
|
||||
..
|
||||
route
|
||||
..
|
||||
savecore
|
||||
..
|
||||
sysctl
|
||||
..
|
||||
..
|
||||
@ -1089,8 +1091,6 @@
|
||||
..
|
||||
cut
|
||||
..
|
||||
dc
|
||||
..
|
||||
diff
|
||||
..
|
||||
diff3
|
||||
|
@ -60,7 +60,7 @@ code in the global variable
|
||||
.Va errno .
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn readlink
|
||||
.Fn fhreadlink
|
||||
system call
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
@ -87,7 +87,8 @@ is no longer valid
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr fhlink 2 ,
|
||||
.Xr fhstat 2
|
||||
.Xr fhstat 2 ,
|
||||
.Xr readlink 2
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn fhreadlink
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd July 8, 2024
|
||||
.Dd November 25, 2024
|
||||
.Dt GETSOCKOPT 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -568,9 +568,14 @@ struct so_splice {
|
||||
.Pp
|
||||
Data received on
|
||||
.Fa s
|
||||
will automatically be transmitted from the socket specified in
|
||||
will automatically be transmitted via the socket specified in
|
||||
.Fa sp_fd
|
||||
without any intervention by userspace.
|
||||
That is, the data will be transmitted via
|
||||
.Fa sp_fd
|
||||
as if userspace had called
|
||||
.Xr send 2
|
||||
directly.
|
||||
Splicing is a one-way operation; a given pair of sockets may be
|
||||
spliced in one or both directions.
|
||||
Currently only connected
|
||||
|
@ -138,6 +138,7 @@ is neither
|
||||
nor a file descriptor associated with a directory.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr fhreadlink 2 ,
|
||||
.Xr lstat 2 ,
|
||||
.Xr stat 2 ,
|
||||
.Xr symlink 2 ,
|
||||
|
@ -263,8 +263,8 @@ icmp_log_redirect="NO" # Set to YES to log ICMP REDIRECT packets
|
||||
network_interfaces="auto" # List of network interfaces (or "auto").
|
||||
cloned_interfaces="" # List of cloned network interfaces to create.
|
||||
#cloned_interfaces="gif0 gif1 gif2 gif3" # Pre-cloning GENERIC config.
|
||||
#ifconfig_lo0="inet 127.0.0.1" # default loopback device configuration.
|
||||
#ifconfig_lo0_alias0="inet 127.0.0.254 netmask 0xffffffff" # Sample alias entry.
|
||||
#ifconfig_lo0="inet 127.0.0.1/8" # default loopback device configuration.
|
||||
#ifconfig_lo0_alias0="inet 127.0.0.254/32" # Sample alias entry.
|
||||
#ifconfig_em0_ipv6="inet6 2001:db8:1::1 prefixlen 64" # Sample IPv6 addr entry
|
||||
#ifconfig_em0_alias0="inet6 2001:db8:2::1 prefixlen 64" # Sample IPv6 alias
|
||||
#ifconfig_em0_name="net0" # Change interface name from em0 to net0.
|
||||
|
@ -27,7 +27,7 @@ _var_run_load() {
|
||||
|
||||
_var_run_save() {
|
||||
if [ ! -d $(dirname ${var_run_mtree}) ]; then
|
||||
mkdir -p ${var_run_mtree}
|
||||
mkdir -p $(dirname ${var_run_mtree})
|
||||
fi
|
||||
mtree -dcbj -p /var/run > ${var_run_mtree}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
.\"
|
||||
.\" $TSHeader: src/sbin/ffsinfo/ffsinfo.8,v 1.3 2000/12/12 19:30:55 tomsoft Exp $
|
||||
.\"
|
||||
.Dd September 8, 2000
|
||||
.Dd November 19, 2024
|
||||
.Dt FFSINFO 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -120,6 +120,7 @@ to
|
||||
.Pa /var/tmp/ffsinfo
|
||||
with all available information.
|
||||
.Sh SEE ALSO
|
||||
.Xr ffs 4 ,
|
||||
.Xr dumpfs 8 ,
|
||||
.Xr fsck 8 ,
|
||||
.Xr gpart 8 ,
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd January 24, 2024
|
||||
.Dd November 19, 2024
|
||||
.Dt MOUNT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -568,6 +568,7 @@ support for a particular file system might be provided either on a static
|
||||
.Xr cd9660 4 ,
|
||||
.Xr devfs 4 ,
|
||||
.Xr ext2fs 4 ,
|
||||
.Xr ffs 4 ,
|
||||
.Xr mac 4 ,
|
||||
.Xr procfs 4 ,
|
||||
.Xr tarfs 4 ,
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd May 18, 2024
|
||||
.Dd November 19, 2024
|
||||
.Dt NEWFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -350,6 +350,7 @@ than the historical defaults
|
||||
This large fragment size may lead to much wasted space
|
||||
on file systems that contain many small files.
|
||||
.Sh SEE ALSO
|
||||
.Xr ffs 4 ,
|
||||
.Xr geom 4 ,
|
||||
.Xr disktab 5 ,
|
||||
.Xr fs 5 ,
|
||||
|
@ -18,4 +18,7 @@ CFLAGS+= -DWITH_CASPER
|
||||
LIBADD+= casper cap_fileargs cap_syslog
|
||||
.endif
|
||||
|
||||
HAS_TESTS=
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
3
sbin/savecore/tests/Makefile
Normal file
3
sbin/savecore/tests/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
ATF_TESTS_SH= livedump_test
|
||||
|
||||
.include <bsd.test.mk>
|
54
sbin/savecore/tests/livedump_test.sh
Normal file
54
sbin/savecore/tests/livedump_test.sh
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
# Copyright (c) 2024 Mark Johnston <markj@FreeBSD.org>
|
||||
#
|
||||
|
||||
atf_test_case livedump_kldstat
|
||||
livedump_kldstat_head()
|
||||
{
|
||||
atf_set "descr" "Test livedump integrity"
|
||||
atf_set "require.progs" kgdb
|
||||
atf_set "require.user" root
|
||||
}
|
||||
livedump_kldstat_body()
|
||||
{
|
||||
atf_check savecore -L .
|
||||
|
||||
kernel=$(sysctl -n kern.bootfile)
|
||||
|
||||
if ! [ -f /usr/lib/debug/${kernel}.debug ]; then
|
||||
atf_skip "No debug symbols for the running kernel"
|
||||
fi
|
||||
|
||||
# Implement kldstat using gdb script.
|
||||
cat >./kldstat.gdb <<'__EOF__'
|
||||
printf "Id Refs Address Size Name\n"
|
||||
set $_lf = linker_files.tqh_first
|
||||
while ($_lf)
|
||||
printf "%2d %4d %p %8x %s\n", $_lf->id, $_lf->refs, $_lf->address, $_lf->size, $_lf->filename
|
||||
set $_lf = $_lf->link.tqe_next
|
||||
end
|
||||
__EOF__
|
||||
|
||||
# Ignore stderr since kgdb prints some warnings about inaccessible
|
||||
# source files.
|
||||
#
|
||||
# Use a script to source the main gdb script, otherwise kgdb prints
|
||||
# a bunch of line noise that is annoying to filter out.
|
||||
echo "source ./kldstat.gdb" > ./script.gdb
|
||||
atf_check -o save:out -e ignore \
|
||||
kgdb -q ${kernel} ./livecore.0 < ./script.gdb
|
||||
|
||||
# Get rid of gunk printed by kgdb.
|
||||
sed -i '' -n -e 's/^(kgdb) //' -e '/^Id Refs /,$p' out
|
||||
|
||||
# The output of kgdb should match the output of kldstat.
|
||||
atf_check -o save:kldstat kldstat
|
||||
atf_check diff kldstat out
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case livedump_kldstat
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd June 3, 2019
|
||||
.Dd November 25, 2024
|
||||
.Dt CCR 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -52,7 +52,10 @@ The driver accelerates AES-CBC, AES-CCM, AES-CTR, AES-GCM, AES-XTS,
|
||||
SHA1, SHA2-224, SHA2-256, SHA2-384, SHA2-512,
|
||||
SHA1-HMAC, SHA2-224-HMAC, SHA2-256-HMAC, SHA2-384-HMAC, and SHA2-512-HMAC
|
||||
operations for
|
||||
.Xr crypto 4
|
||||
.Xr crypto 9
|
||||
consumers such as
|
||||
.Xr ktls 4 ,
|
||||
.Xr geli 4 ,
|
||||
and
|
||||
.Xr ipsec 4 .
|
||||
The driver also supports chaining one of AES-CBC, AES-CTR, or AES-XTS with
|
||||
@ -97,7 +100,11 @@ email all the specific information related to the issue to
|
||||
.Sh SEE ALSO
|
||||
.Xr crypto 4 ,
|
||||
.Xr cxgbe 4 ,
|
||||
.Xr ipsec 4
|
||||
.Xr geli 4 ,
|
||||
.Xr ipsec 4 ,
|
||||
.Xr ktls 4 ,
|
||||
.Xr crypto 7 ,
|
||||
.Xr crypto 9
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
|
@ -239,10 +239,10 @@ struct preloaded_file
|
||||
size_t f_size; /* file size */
|
||||
struct kernel_module *f_modules; /* list of modules if any */
|
||||
struct preloaded_file *f_next; /* next file */
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#if defined(__amd64__) || (defined(__i386__) && defined(EFI))
|
||||
bool f_kernphys_relocatable;
|
||||
#endif
|
||||
#if defined(__i386__)
|
||||
#if defined(__i386__) && !defined(EFI)
|
||||
bool f_tg_kernel_support;
|
||||
#endif
|
||||
};
|
||||
|
@ -217,7 +217,7 @@ static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#if defined(__amd64__) || (defined(__i386__) && defined(EFI))
|
||||
static bool
|
||||
is_kernphys_relocatable(elf_file_t ef)
|
||||
{
|
||||
@ -491,10 +491,10 @@ __elfN(loadfile_raw)(char *filename, uint64_t dest,
|
||||
/* Load OK, return module pointer */
|
||||
*result = (struct preloaded_file *)fp;
|
||||
err = 0;
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#if defined(__amd64__) || (defined(__i386__) && defined(EFI))
|
||||
fp->f_kernphys_relocatable = multiboot || is_kernphys_relocatable(&ef);
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
#if defined(__i386__) && !defined(EFI)
|
||||
fp->f_tg_kernel_support = is_tg_kernel_support(fp, &ef);
|
||||
#endif
|
||||
goto out;
|
||||
|
@ -42,9 +42,6 @@
|
||||
|
||||
#include "loader_efi.h"
|
||||
|
||||
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
static int elf64_exec(struct preloaded_file *amp);
|
||||
static int elf64_obj_exec(struct preloaded_file *amp);
|
||||
|
||||
@ -74,8 +71,6 @@ static pdp_entry_t *PT3_l, *PT3_u;
|
||||
static pd_entry_t *PT2;
|
||||
static pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1;
|
||||
|
||||
extern EFI_PHYSICAL_ADDRESS staging;
|
||||
|
||||
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
|
||||
uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry);
|
||||
|
||||
@ -106,8 +101,7 @@ elf64_exec(struct preloaded_file *fp)
|
||||
ehdr = (Elf_Ehdr *)&(md->md_data);
|
||||
|
||||
trampcode = copy_staging == COPY_STAGING_ENABLE ?
|
||||
(vm_offset_t)0x0000000040000000 /* 1G */ :
|
||||
(vm_offset_t)0x0000000100000000; /* 4G */;
|
||||
(vm_offset_t)G(1) : (vm_offset_t)G(4);
|
||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
|
||||
(EFI_PHYSICAL_ADDRESS *)&trampcode);
|
||||
if (EFI_ERROR(err)) {
|
||||
@ -122,7 +116,7 @@ elf64_exec(struct preloaded_file *fp)
|
||||
trampoline = (void *)trampcode;
|
||||
|
||||
if (copy_staging == COPY_STAGING_ENABLE) {
|
||||
PT4 = (pml4_entry_t *)0x0000000040000000; /* 1G */
|
||||
PT4 = (pml4_entry_t *)G(1);
|
||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
|
||||
(EFI_PHYSICAL_ADDRESS *)&PT4);
|
||||
if (EFI_ERROR(err)) {
|
||||
@ -159,11 +153,11 @@ elf64_exec(struct preloaded_file *fp)
|
||||
/*
|
||||
* The L2 page slots are mapped with 2MB pages for 1GB.
|
||||
*/
|
||||
PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024);
|
||||
PT2[i] = (pd_entry_t)i * M(2);
|
||||
PT2[i] |= PG_V | PG_RW | PG_PS;
|
||||
}
|
||||
} else {
|
||||
PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */
|
||||
PT4 = (pml4_entry_t *)G(4);
|
||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9,
|
||||
(EFI_PHYSICAL_ADDRESS *)&PT4);
|
||||
if (EFI_ERROR(err)) {
|
||||
|
@ -57,8 +57,6 @@ extern int elf32_loadfile_raw(char *filename, uint64_t dest,
|
||||
extern int elf64_load_modmetadata(struct preloaded_file *fp, uint64_t dest);
|
||||
extern int elf64_obj_loadfile(char *filename, uint64_t dest,
|
||||
struct preloaded_file **result);
|
||||
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
extern void multiboot2_exec(void *entry, uint64_t multiboot_info,
|
||||
uint64_t stack);
|
||||
|
@ -40,8 +40,6 @@
|
||||
#include "bootstrap.h"
|
||||
#include "loader_efi.h"
|
||||
|
||||
extern int bi_load(char *, vm_offset_t *, vm_offset_t *, bool);
|
||||
|
||||
static int
|
||||
__elfN(arm_load)(char *filename, uint64_t dest,
|
||||
struct preloaded_file **result)
|
||||
|
@ -42,9 +42,6 @@
|
||||
static int elf64_exec(struct preloaded_file *amp);
|
||||
static int elf64_obj_exec(struct preloaded_file *amp);
|
||||
|
||||
int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
static struct file_format arm64_elf = {
|
||||
elf64_loadfile,
|
||||
elf64_exec
|
||||
|
@ -28,7 +28,11 @@
|
||||
#define __ELF_WORD_SIZE 64
|
||||
#include <sys/param.h>
|
||||
#include <sys/linker.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/elf.h>
|
||||
#include <machine/pmap_pae.h>
|
||||
#include <machine/segments.h>
|
||||
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
@ -37,9 +41,6 @@
|
||||
|
||||
#include "loader_efi.h"
|
||||
|
||||
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
static int elf64_exec(struct preloaded_file *amp);
|
||||
static int elf64_obj_exec(struct preloaded_file *amp);
|
||||
|
||||
@ -59,40 +60,14 @@ struct file_format *file_formats[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
struct gdtr {
|
||||
uint16_t size;
|
||||
uint64_t ptr;
|
||||
} __packed;
|
||||
|
||||
#define PG_V 0x001
|
||||
#define PG_RW 0x002
|
||||
#define PG_PS 0x080
|
||||
|
||||
#define GDT_P 0x00800000000000
|
||||
#define GDT_E 0x00080000000000
|
||||
#define GDT_S 0x00100000000000
|
||||
#define GDT_RW 0x00020000000000
|
||||
#define GDT_L 0x20000000000000
|
||||
|
||||
#define M(x) ((x) * 1024 * 1024)
|
||||
#define G(x) (1ULL * (x) * 1024 * 1024 * 1024)
|
||||
|
||||
typedef uint64_t p4_entry_t;
|
||||
typedef uint64_t p3_entry_t;
|
||||
typedef uint64_t p2_entry_t;
|
||||
typedef uint64_t gdt_t;
|
||||
|
||||
static p4_entry_t *PT4;
|
||||
static p3_entry_t *PT3;
|
||||
static p3_entry_t *PT3_l, *PT3_u;
|
||||
static p2_entry_t *PT2;
|
||||
static p2_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1;
|
||||
static gdt_t *GDT;
|
||||
|
||||
extern EFI_PHYSICAL_ADDRESS staging;
|
||||
/*
|
||||
* i386's pmap_pae.h doesn't provide this, so
|
||||
* just typedef our own.
|
||||
*/
|
||||
typedef pdpt_entry_t pml4_entry_t;
|
||||
|
||||
static void (*trampoline)(uint32_t stack, void *copy_finish, uint32_t kernend,
|
||||
uint32_t modulep, uint64_t *pagetable, struct gdtr *gdtr, uint64_t entry);
|
||||
uint32_t modulep, uint64_t *pagetable, void *gdtr, uint64_t entry);
|
||||
|
||||
extern void *amd64_tramp;
|
||||
extern uint32_t amd64_tramp_size;
|
||||
@ -105,12 +80,23 @@ extern uint32_t amd64_tramp_size;
|
||||
static int
|
||||
elf64_exec(struct preloaded_file *fp)
|
||||
{
|
||||
/*
|
||||
* segments.h gives us a 32-bit gdtr, but
|
||||
* we want a 64-bit one, so define our own.
|
||||
*/
|
||||
struct {
|
||||
uint16_t rd_limit;
|
||||
uint64_t rd_base;
|
||||
} __packed *gdtr;
|
||||
EFI_PHYSICAL_ADDRESS ptr;
|
||||
EFI_ALLOCATE_TYPE type;
|
||||
EFI_STATUS err;
|
||||
struct file_metadata *md;
|
||||
struct gdtr *gdtr;
|
||||
Elf_Ehdr *ehdr;
|
||||
pml4_entry_t *PT4;
|
||||
pdpt_entry_t *PT3;
|
||||
pd_entry_t *PT2;
|
||||
struct user_segment_descriptor *gdt;
|
||||
vm_offset_t modulep, kernend, trampstack;
|
||||
int i;
|
||||
|
||||
@ -131,36 +117,47 @@ elf64_exec(struct preloaded_file *fp)
|
||||
return (EFTYPE);
|
||||
ehdr = (Elf_Ehdr *)&(md->md_data);
|
||||
|
||||
/*
|
||||
* Make our temporary stack 32 bytes big, which is
|
||||
* a little more than we need.
|
||||
*/
|
||||
ptr = G(1);
|
||||
err = BS->AllocatePages(type, EfiLoaderCode,
|
||||
EFI_SIZE_TO_PAGES(amd64_tramp_size + 32), &ptr);
|
||||
EFI_SIZE_TO_PAGES(amd64_tramp_size), &ptr);
|
||||
if (EFI_ERROR(err)) {
|
||||
printf("Unable to allocate trampoline\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
trampoline = (void *)(uintptr_t)ptr;
|
||||
trampstack = ptr + amd64_tramp_size + 32;
|
||||
bcopy(&amd64_tramp, trampoline, amd64_tramp_size);
|
||||
|
||||
/*
|
||||
* Allocate enough space for the GDTR + two GDT segments +
|
||||
* our temporary stack (28 bytes).
|
||||
*/
|
||||
#define DATASZ (sizeof(*gdtr) + \
|
||||
sizeof(struct user_segment_descriptor) * 2 + 28)
|
||||
|
||||
ptr = G(1);
|
||||
err = BS->AllocatePages(type, EfiLoaderData,
|
||||
EFI_SIZE_TO_PAGES(sizeof(struct gdtr) + sizeof(uint64_t) * 2), &ptr);
|
||||
EFI_SIZE_TO_PAGES(DATASZ), &ptr);
|
||||
if (EFI_ERROR(err)) {
|
||||
printf("Unable to allocate GDT\n");
|
||||
printf("Unable to allocate GDT and stack\n");
|
||||
BS->FreePages((uintptr_t)trampoline, 1);
|
||||
return (ENOMEM);
|
||||
}
|
||||
GDT = (gdt_t *)(uintptr_t)ptr;
|
||||
GDT[1] = GDT_P | GDT_E | GDT_S | GDT_RW | GDT_L; /* CS */
|
||||
GDT[0] = 0;
|
||||
gdtr = (struct gdtr *)&GDT[2];
|
||||
gdtr->size = sizeof(uint64_t) * 2 - 1;
|
||||
gdtr->ptr = (uintptr_t)GDT;
|
||||
|
||||
trampstack = ptr + DATASZ;
|
||||
|
||||
#undef DATASZ
|
||||
|
||||
gdt = (void *)(uintptr_t)ptr;
|
||||
gdt[0] = (struct user_segment_descriptor) { 0 };
|
||||
gdt[1] = (struct user_segment_descriptor) {
|
||||
.sd_p = 1, .sd_long = 1, .sd_type = SDT_MEMERC
|
||||
};
|
||||
|
||||
gdtr = (void *)(uintptr_t)(ptr +
|
||||
sizeof(struct user_segment_descriptor) * 2);
|
||||
gdtr->rd_limit = sizeof(struct user_segment_descriptor) * 2 - 1;
|
||||
gdtr->rd_base = (uintptr_t)gdt;
|
||||
|
||||
if (type == AllocateMaxAddress) {
|
||||
/* Copy staging enabled */
|
||||
@ -171,10 +168,10 @@ elf64_exec(struct preloaded_file *fp)
|
||||
if (EFI_ERROR(err)) {
|
||||
printf("Unable to allocate trampoline page table\n");
|
||||
BS->FreePages((uintptr_t)trampoline, 1);
|
||||
BS->FreePages((uintptr_t)GDT, 1);
|
||||
BS->FreePages((uintptr_t)gdt, 1);
|
||||
return (ENOMEM);
|
||||
}
|
||||
PT4 = (p4_entry_t *)(uintptr_t)ptr;
|
||||
PT4 = (pml4_entry_t *)(uintptr_t)ptr;
|
||||
|
||||
PT3 = &PT4[512];
|
||||
PT2 = &PT3[512];
|
||||
@ -203,15 +200,18 @@ elf64_exec(struct preloaded_file *fp)
|
||||
PT2[i] = (i * M(2)) | PG_V | PG_RW | PG_PS;
|
||||
}
|
||||
} else {
|
||||
pdpt_entry_t *PT3_l, *PT3_u;
|
||||
pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1;
|
||||
|
||||
err = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
|
||||
EFI_SIZE_TO_PAGES(512 * 9 * sizeof(uint64_t)), &ptr);
|
||||
if (EFI_ERROR(err)) {
|
||||
printf("Unable to allocate trampoline page table\n");
|
||||
BS->FreePages((uintptr_t)trampoline, 1);
|
||||
BS->FreePages((uintptr_t)GDT, 1);
|
||||
BS->FreePages((uintptr_t)gdt, 1);
|
||||
return (ENOMEM);
|
||||
}
|
||||
PT4 = (p4_entry_t *)(uintptr_t)ptr;
|
||||
PT4 = (pml4_entry_t *)(uintptr_t)ptr;
|
||||
|
||||
PT3_l = &PT4[512];
|
||||
PT3_u = &PT3_l[512];
|
||||
@ -229,7 +229,7 @@ elf64_exec(struct preloaded_file *fp)
|
||||
PT3_l[2] = (uintptr_t)PT2_l2 | PG_V | PG_RW;
|
||||
PT3_l[3] = (uintptr_t)PT2_l3 | PG_V | PG_RW;
|
||||
for (i = 0; i < 2048; i++) {
|
||||
PT2_l0[i] = ((p2_entry_t)i * M(2)) | PG_V | PG_RW | PG_PS;
|
||||
PT2_l0[i] = ((pd_entry_t)i * M(2)) | PG_V | PG_RW | PG_PS;
|
||||
}
|
||||
|
||||
/* mapping of kernel 2G below top */
|
||||
@ -248,7 +248,7 @@ elf64_exec(struct preloaded_file *fp)
|
||||
printf(
|
||||
"staging %#llx (%scopying) tramp %p PT4 %p GDT %p\n"
|
||||
"Start @ %#llx ...\n", staging,
|
||||
type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, GDT,
|
||||
type == AllocateMaxAddress ? "" : "not ", trampoline, PT4, gdt,
|
||||
ehdr->e_entry
|
||||
);
|
||||
|
||||
|
@ -40,8 +40,6 @@
|
||||
#include "bootstrap.h"
|
||||
#include "loader_efi.h"
|
||||
|
||||
extern int bi_load(char *, vm_offset_t *, vm_offset_t *, bool);
|
||||
|
||||
static int
|
||||
__elfN(exec)(struct preloaded_file *fp)
|
||||
{
|
||||
|
@ -64,9 +64,6 @@
|
||||
#include "geliboot.h"
|
||||
#endif
|
||||
|
||||
int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
static int
|
||||
bi_getboothowto(char *kargs)
|
||||
{
|
||||
|
@ -35,9 +35,6 @@
|
||||
|
||||
#include "loader_efi.h"
|
||||
|
||||
#define M(x) ((x) * 1024 * 1024)
|
||||
#define G(x) (1ULL * (x) * 1024 * 1024 * 1024)
|
||||
|
||||
#if defined(__amd64__)
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/specialreg.h>
|
||||
@ -181,12 +178,7 @@ out:
|
||||
#define EFI_STAGING_SIZE DEFAULT_EFI_STAGING_SIZE
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
|
||||
defined(__riscv) || defined(__i386__)
|
||||
#define EFI_STAGING_2M_ALIGN 1
|
||||
#else
|
||||
#define EFI_STAGING_2M_ALIGN 0
|
||||
#endif
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#define EFI_STAGING_SLOP M(8)
|
||||
|
@ -41,6 +41,10 @@ enum {
|
||||
extern int copy_staging;
|
||||
#endif
|
||||
|
||||
/* Useful for various calculations */
|
||||
#define M(x) ((x) * 1024 * 1024)
|
||||
#define G(x) (1ULL * (x) * 1024 * 1024 * 1024)
|
||||
|
||||
extern EFI_LOADED_IMAGE *boot_img;
|
||||
|
||||
int efi_autoload(void);
|
||||
@ -55,4 +59,12 @@ void * efi_translate(vm_offset_t ptr);
|
||||
void efi_copy_finish(void);
|
||||
void efi_copy_finish_nop(void);
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
/* Need this to setup page tables */
|
||||
extern EFI_PHYSICAL_ADDRESS staging;
|
||||
#endif
|
||||
|
||||
int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
#endif /* _LOADER_EFI_COPY_H_ */
|
||||
|
@ -28,8 +28,11 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/linker.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <string.h>
|
||||
#include <machine/bootinfo.h>
|
||||
#include <machine/pmap_pae.h>
|
||||
#include <machine/elf.h>
|
||||
#include <stand.h>
|
||||
|
||||
@ -43,16 +46,15 @@ static int elf64_obj_exec(struct preloaded_file *amp);
|
||||
struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
|
||||
struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
|
||||
|
||||
#define PG_V 0x001
|
||||
#define PG_RW 0x002
|
||||
#define PG_PS 0x080
|
||||
/*
|
||||
* i386's pmap_pae.h doesn't provide this, so
|
||||
* just typedef our own.
|
||||
*/
|
||||
typedef pdpt_entry_t pml4_entry_t;
|
||||
|
||||
typedef uint64_t p4_entry_t;
|
||||
typedef uint64_t p3_entry_t;
|
||||
typedef uint64_t p2_entry_t;
|
||||
extern p4_entry_t PT4[];
|
||||
extern p3_entry_t PT3[];
|
||||
extern p2_entry_t PT2[];
|
||||
extern pml4_entry_t PT4[];
|
||||
extern pdpt_entry_t PT3[];
|
||||
extern pd_entry_t PT2[];
|
||||
|
||||
uint32_t entry_hi;
|
||||
uint32_t entry_lo;
|
||||
@ -91,11 +93,11 @@ elf64_exec(struct preloaded_file *fp)
|
||||
*/
|
||||
for (i = 0; i < 512; i++) {
|
||||
/* Each slot of the level 4 pages points to the same level 3 page */
|
||||
PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]);
|
||||
PT4[i] = (pml4_entry_t)VTOP((uintptr_t)&PT3[0]);
|
||||
PT4[i] |= PG_V | PG_RW;
|
||||
|
||||
/* Each slot of the level 3 pages points to the same level 2 page */
|
||||
PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]);
|
||||
PT3[i] = (pdpt_entry_t)VTOP((uintptr_t)&PT2[0]);
|
||||
PT3[i] |= PG_V | PG_RW;
|
||||
|
||||
/* The level 2 page slots are mapped with 2MB pages for 1GB. */
|
||||
|
@ -42,7 +42,6 @@
|
||||
|
||||
#include "bootstrap.h"
|
||||
#include "kboot.h"
|
||||
#include "bootstrap.h"
|
||||
|
||||
#include "platform/acfreebsd.h"
|
||||
#include "acconfig.h"
|
||||
@ -70,8 +69,11 @@ extern uint32_t efi_map_size;
|
||||
extern vm_paddr_t efi_map_phys_src; /* From DTB */
|
||||
extern vm_paddr_t efi_map_phys_dst; /* From our memory map metadata module */
|
||||
|
||||
/* Usually provided by loader_efi.h */
|
||||
#ifndef EFI
|
||||
int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
#endif
|
||||
|
||||
static struct file_format arm64_elf = {
|
||||
elf64_loadfile,
|
||||
|
@ -56,6 +56,10 @@
|
||||
|
||||
static EFI_GUID acpi_guid = ACPI_TABLE_GUID;
|
||||
static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
|
||||
#else
|
||||
/* Usually provided by loader_efi.h */
|
||||
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
#endif
|
||||
|
||||
#ifdef EFI
|
||||
@ -64,9 +68,6 @@ static EFI_GUID acpi20_guid = ACPI_20_TABLE_GUID;
|
||||
#define LOADER_PAGE_SIZE PAGE_SIZE
|
||||
#endif
|
||||
|
||||
extern int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
|
||||
bool exit_bs);
|
||||
|
||||
static int elf64_exec(struct preloaded_file *amp);
|
||||
static int elf64_obj_exec(struct preloaded_file *amp);
|
||||
|
||||
@ -121,8 +122,6 @@ static pd_entry_t *PT2_l0, *PT2_l1, *PT2_l2, *PT2_l3, *PT2_u0, *PT2_u1;
|
||||
static pdp_entry_t *PT3;
|
||||
static pd_entry_t *PT2;
|
||||
|
||||
extern EFI_PHYSICAL_ADDRESS staging;
|
||||
|
||||
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
|
||||
uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry);
|
||||
#endif
|
||||
@ -210,8 +209,7 @@ elf64_exec(struct preloaded_file *fp)
|
||||
|
||||
#ifdef EFI
|
||||
trampcode = copy_staging == COPY_STAGING_ENABLE ?
|
||||
(vm_offset_t)0x0000000040000000 /* 1G */ :
|
||||
(vm_offset_t)0x0000000100000000; /* 4G */;
|
||||
(vm_offset_t)G(1) : (vm_offset_t)G(4);
|
||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1,
|
||||
(EFI_PHYSICAL_ADDRESS *)&trampcode);
|
||||
if (EFI_ERROR(err)) {
|
||||
@ -235,7 +233,7 @@ elf64_exec(struct preloaded_file *fp)
|
||||
|
||||
#ifdef EFI
|
||||
if (copy_staging == COPY_STAGING_ENABLE) {
|
||||
PT4 = (pml4_entry_t *)0x0000000040000000; /* 1G */
|
||||
PT4 = (pml4_entry_t *)G(1);
|
||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 3,
|
||||
(EFI_PHYSICAL_ADDRESS *)&PT4);
|
||||
if (EFI_ERROR(err)) {
|
||||
@ -272,11 +270,11 @@ elf64_exec(struct preloaded_file *fp)
|
||||
/*
|
||||
* The L2 page slots are mapped with 2MB pages for 1GB.
|
||||
*/
|
||||
PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024);
|
||||
PT2[i] = (pd_entry_t)i * M(2);
|
||||
PT2[i] |= PG_V | PG_RW | PG_PS;
|
||||
}
|
||||
} else {
|
||||
PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */
|
||||
PT4 = (pml4_entry_t *)G(4);
|
||||
err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9,
|
||||
(EFI_PHYSICAL_ADDRESS *)&PT4);
|
||||
if (EFI_ERROR(err)) {
|
||||
|
@ -31,9 +31,10 @@
|
||||
#ifdef DEBUG
|
||||
#include <machine/_inttypes.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <i386/include/bootinfo.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/elf.h>
|
||||
#include <machine/segments.h>
|
||||
#include <stand.h>
|
||||
|
||||
#include "bootstrap.h"
|
||||
@ -45,35 +46,21 @@ static int elf64_obj_exec(struct preloaded_file *amp);
|
||||
struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
|
||||
struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
|
||||
|
||||
#define MSR_EFER 0xc0000080
|
||||
#define EFER_LME 0x00000100
|
||||
#define EFER_LMA 0x00000400 /* Long mode active (R) */
|
||||
#define CR4_PAE 0x00000020
|
||||
#define CR4_VMXE (1UL << 13)
|
||||
#define CR4_PSE 0x00000010
|
||||
#define CR0_PG 0x80000000
|
||||
#define CR0_PE 0x00000001 /* Protected mode Enable */
|
||||
#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */
|
||||
|
||||
#define PG_V 0x001
|
||||
#define PG_RW 0x002
|
||||
#define PG_PS 0x080
|
||||
|
||||
typedef uint64_t p4_entry_t;
|
||||
typedef uint64_t p3_entry_t;
|
||||
typedef uint64_t p2_entry_t;
|
||||
|
||||
#define GUEST_NULL_SEL 0
|
||||
#define GUEST_CODE_SEL 1
|
||||
#define GUEST_DATA_SEL 2
|
||||
#define GUEST_GDTR_LIMIT (3 * 8 - 1)
|
||||
|
||||
static void
|
||||
setup_freebsd_gdt(uint64_t *gdtr)
|
||||
setup_freebsd_gdt(struct user_segment_descriptor *gdt)
|
||||
{
|
||||
gdtr[GUEST_NULL_SEL] = 0;
|
||||
gdtr[GUEST_CODE_SEL] = 0x0020980000000000;
|
||||
gdtr[GUEST_DATA_SEL] = 0x0000900000000000;
|
||||
gdt[GUEST_NULL_SEL] = (struct user_segment_descriptor) { 0 };
|
||||
gdt[GUEST_CODE_SEL] = (struct user_segment_descriptor) {
|
||||
.sd_p = 1, .sd_long = 1, .sd_type = SDT_MEME
|
||||
};
|
||||
gdt[GUEST_DATA_SEL] = (struct user_segment_descriptor) {
|
||||
.sd_p = 1, .sd_type = SDT_MEMRO
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
@ -90,10 +77,10 @@ elf64_exec(struct preloaded_file *fp)
|
||||
int err;
|
||||
int i;
|
||||
uint32_t stack[1024];
|
||||
p4_entry_t PT4[512];
|
||||
p3_entry_t PT3[512];
|
||||
p2_entry_t PT2[512];
|
||||
uint64_t gdtr[3];
|
||||
pml4_entry_t PT4[512];
|
||||
pdp_entry_t PT3[512];
|
||||
pd_entry_t PT2[512];
|
||||
struct user_segment_descriptor gdt[3];
|
||||
|
||||
if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
|
||||
return(EFTYPE);
|
||||
@ -122,11 +109,11 @@ elf64_exec(struct preloaded_file *fp)
|
||||
*/
|
||||
for (i = 0; i < 512; i++) {
|
||||
/* Each slot of the level 4 pages points to the same level 3 page */
|
||||
PT4[i] = (p4_entry_t) 0x3000;
|
||||
PT4[i] = (pml4_entry_t) 0x3000;
|
||||
PT4[i] |= PG_V | PG_RW;
|
||||
|
||||
/* Each slot of the level 3 pages points to the same level 2 page */
|
||||
PT3[i] = (p3_entry_t) 0x4000;
|
||||
PT3[i] = (pdp_entry_t) 0x4000;
|
||||
PT3[i] |= PG_V | PG_RW;
|
||||
|
||||
/* The level 2 page slots are mapped with 2MB pages for 1GB. */
|
||||
@ -154,9 +141,9 @@ elf64_exec(struct preloaded_file *fp)
|
||||
CALLBACK(setcr, 3, 0x2000);
|
||||
CALLBACK(setcr, 0, CR0_PG | CR0_PE | CR0_NE);
|
||||
|
||||
setup_freebsd_gdt(gdtr);
|
||||
CALLBACK(copyin, gdtr, 0x5000, sizeof(gdtr));
|
||||
CALLBACK(setgdt, 0x5000, sizeof(gdtr));
|
||||
setup_freebsd_gdt(gdt);
|
||||
CALLBACK(copyin, gdt, 0x5000, sizeof(gdt));
|
||||
CALLBACK(setgdt, 0x5000, sizeof(gdt));
|
||||
|
||||
CALLBACK(exec, ehdr->e_entry);
|
||||
|
||||
|
@ -4082,7 +4082,19 @@ pmap_qremove(vm_offset_t sva, int count)
|
||||
|
||||
va = sva;
|
||||
while (count-- > 0) {
|
||||
/*
|
||||
* pmap_enter() calls within the kernel virtual
|
||||
* address space happen on virtual addresses from
|
||||
* subarenas that import superpage-sized and -aligned
|
||||
* address ranges. So, the virtual address that we
|
||||
* allocate to use with pmap_qenter() can't be close
|
||||
* enough to one of those pmap_enter() calls for it to
|
||||
* be caught up in a promotion.
|
||||
*/
|
||||
KASSERT(va >= VM_MIN_KERNEL_ADDRESS, ("usermode va %lx", va));
|
||||
KASSERT((*vtopde(va) & X86_PG_PS) == 0,
|
||||
("pmap_qremove on promoted va %#lx", va));
|
||||
|
||||
pmap_kremove(va);
|
||||
va += PAGE_SIZE;
|
||||
}
|
||||
@ -10506,8 +10518,7 @@ pmap_map_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
|
||||
{
|
||||
vm_paddr_t paddr;
|
||||
bool needs_mapping;
|
||||
pt_entry_t *pte;
|
||||
int cache_bits, error __unused, i;
|
||||
int error __unused, i;
|
||||
|
||||
/*
|
||||
* Allocate any KVA space that we need, this is done in a separate
|
||||
@ -10552,11 +10563,8 @@ pmap_map_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
|
||||
*/
|
||||
pmap_qenter(vaddr[i], &page[i], 1);
|
||||
} else {
|
||||
pte = vtopte(vaddr[i]);
|
||||
cache_bits = pmap_cache_bits(kernel_pmap,
|
||||
page[i]->md.pat_mode, false);
|
||||
pte_store(pte, paddr | X86_PG_RW | X86_PG_V |
|
||||
cache_bits);
|
||||
pmap_kenter_attr(vaddr[i], paddr,
|
||||
page[i]->md.pat_mode);
|
||||
pmap_invlpg(kernel_pmap, vaddr[i]);
|
||||
}
|
||||
}
|
||||
|
@ -101,14 +101,19 @@ get_vfpcontext(struct thread *td, mcontext_vfp_t *vfp)
|
||||
P_SHOULDSTOP(td->td_proc));
|
||||
|
||||
pcb = td->td_pcb;
|
||||
if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0 && td == curthread) {
|
||||
if (td == curthread) {
|
||||
critical_enter();
|
||||
vfp_store(&pcb->pcb_vfpstate, false);
|
||||
critical_exit();
|
||||
}
|
||||
KASSERT(pcb->pcb_vfpsaved == &pcb->pcb_vfpstate,
|
||||
("Called get_vfpcontext while the kernel is using the VFP"));
|
||||
memcpy(vfp, &pcb->pcb_vfpstate, sizeof(*vfp));
|
||||
|
||||
memset(vfp, 0, sizeof(*vfp));
|
||||
memcpy(vfp->mcv_reg, pcb->pcb_vfpstate.reg,
|
||||
sizeof(vfp->mcv_reg));
|
||||
vfp->mcv_fpscr = pcb->pcb_vfpstate.fpscr;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -127,7 +132,10 @@ set_vfpcontext(struct thread *td, mcontext_vfp_t *vfp)
|
||||
}
|
||||
KASSERT(pcb->pcb_vfpsaved == &pcb->pcb_vfpstate,
|
||||
("Called set_vfpcontext while the kernel is using the VFP"));
|
||||
memcpy(&pcb->pcb_vfpstate, vfp, sizeof(*vfp));
|
||||
memcpy(pcb->pcb_vfpstate.reg, vfp->mcv_reg,
|
||||
sizeof(pcb->pcb_vfpstate.reg));
|
||||
pcb->pcb_vfpstate.fpscr = vfp->mcv_fpscr;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -163,8 +171,6 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
|
||||
{
|
||||
struct trapframe *tf = td->td_frame;
|
||||
__greg_t *gr = mcp->__gregs;
|
||||
mcontext_vfp_t mcontext_vfp;
|
||||
int rv;
|
||||
|
||||
if (clear_ret & GET_MC_CLEAR_RET) {
|
||||
gr[_REG_R0] = 0;
|
||||
@ -189,19 +195,9 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
|
||||
gr[_REG_LR] = tf->tf_usr_lr;
|
||||
gr[_REG_PC] = tf->tf_pc;
|
||||
|
||||
#ifdef VFP
|
||||
if (mcp->mc_vfp_size != sizeof(mcontext_vfp_t))
|
||||
return (EINVAL);
|
||||
get_vfpcontext(td, &mcontext_vfp);
|
||||
#else
|
||||
bzero(&mcontext_vfp, sizeof(mcontext_vfp));
|
||||
#endif
|
||||
|
||||
if (mcp->mc_vfp_ptr != NULL) {
|
||||
rv = copyout(&mcontext_vfp, mcp->mc_vfp_ptr, sizeof(mcontext_vfp));
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
}
|
||||
mcp->mc_vfp_size = 0;
|
||||
mcp->mc_vfp_ptr = NULL;
|
||||
memset(&mcp->mc_spare, 0, sizeof(mcp->mc_spare));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -315,6 +311,16 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
|
||||
/* Populate the siginfo frame. */
|
||||
bzero(&frame, sizeof(frame));
|
||||
get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
|
||||
|
||||
#ifdef VFP
|
||||
get_vfpcontext(td, &frame.sf_vfp);
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_size = sizeof(fp->sf_vfp);
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_ptr = &fp->sf_vfp;
|
||||
#else
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_size = 0;
|
||||
frame.sf_uc.uc_mcontext.mc_vfp_ptr = NULL;
|
||||
#endif
|
||||
|
||||
frame.sf_si = ksi->ksi_info;
|
||||
frame.sf_uc.uc_sigmask = *mask;
|
||||
frame.sf_uc.uc_stack = td->td_sigstk;
|
||||
|
@ -36,6 +36,7 @@ riscv/riscv/bus_machdep.c standard
|
||||
riscv/riscv/bus_space_asm.S standard
|
||||
riscv/riscv/busdma_bounce.c standard
|
||||
riscv/riscv/busdma_machdep.c standard
|
||||
riscv/riscv/cache.c standard
|
||||
riscv/riscv/clock.c standard
|
||||
riscv/riscv/copyinout.S standard
|
||||
riscv/riscv/cpufunc_asm.S standard
|
||||
@ -83,5 +84,7 @@ riscv/vmm/vmm_riscv.c optional vmm
|
||||
riscv/vmm/vmm_sbi.c optional vmm
|
||||
riscv/vmm/vmm_switch.S optional vmm
|
||||
|
||||
riscv/thead/thead.c standard
|
||||
|
||||
# Zstd
|
||||
contrib/zstd/lib/freebsd/zstd_kfreebsd.c optional zstdio compile-with ${ZSTD_C}
|
||||
|
@ -158,7 +158,7 @@ SYSCTL_INT(_hw_ena, OID_AUTO, enable_9k_mbufs, CTLFLAG_RDTUN,
|
||||
int ena_force_large_llq_header = ENA_LLQ_HEADER_SIZE_POLICY_DEFAULT;
|
||||
SYSCTL_INT(_hw_ena, OID_AUTO, force_large_llq_header, CTLFLAG_RDTUN,
|
||||
&ena_force_large_llq_header, 0,
|
||||
"Change default LLQ entry size received from the device\n");
|
||||
"Change default LLQ entry size received from the device");
|
||||
|
||||
int ena_rss_table_size = ENA_RX_RSS_TABLE_SIZE;
|
||||
|
||||
|
@ -122,6 +122,7 @@ struct hms_softc {
|
||||
hid_size_t isize;
|
||||
uint32_t drift_cnt;
|
||||
uint32_t drift_thresh;
|
||||
struct hid_location wheel_loc;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -131,6 +132,7 @@ hms_intr(void *context, void *buf, hid_size_t len)
|
||||
{
|
||||
struct hidmap *hm = context;
|
||||
struct hms_softc *sc = device_get_softc(hm->dev);
|
||||
int32_t wheel;
|
||||
|
||||
if (len > sc->isize)
|
||||
len = sc->isize;
|
||||
@ -140,8 +142,18 @@ hms_intr(void *context, void *buf, hid_size_t len)
|
||||
* to return last report data in sampling mode even after touch has
|
||||
* been ended. That results in cursor drift. Filter out such a
|
||||
* reports through comparing with previous one.
|
||||
*
|
||||
* Except this results in dropping consecutive mouse wheel events,
|
||||
* because differently from cursor movement they always move by the
|
||||
* same amount. So, don't do it when there's mouse wheel movement.
|
||||
*/
|
||||
if (len == sc->last_irsize && memcmp(buf, sc->last_ir, len) == 0) {
|
||||
if (sc->wheel_loc.size != 0)
|
||||
wheel = hid_get_data(buf, len, &sc->wheel_loc);
|
||||
else
|
||||
wheel = 0;
|
||||
|
||||
if (len == sc->last_irsize && memcmp(buf, sc->last_ir, len) == 0 &&
|
||||
wheel == 0) {
|
||||
sc->drift_cnt++;
|
||||
if (sc->drift_thresh != 0 && sc->drift_cnt >= sc->drift_thresh)
|
||||
return;
|
||||
@ -285,9 +297,25 @@ hms_attach(device_t dev)
|
||||
/* Count number of input usages of variable type mapped to buttons */
|
||||
for (hi = sc->hm.hid_items;
|
||||
hi < sc->hm.hid_items + sc->hm.nhid_items;
|
||||
hi++)
|
||||
hi++) {
|
||||
if (hi->type == HIDMAP_TYPE_VARIABLE && hi->evtype == EV_KEY)
|
||||
nbuttons++;
|
||||
#ifdef IICHID_SAMPLING
|
||||
/*
|
||||
* Make note of which part of the report descriptor is the wheel.
|
||||
*/
|
||||
if (hi->type == HIDMAP_TYPE_VARIABLE &&
|
||||
hi->evtype == EV_REL && hi->code == REL_WHEEL) {
|
||||
sc->wheel_loc = hi->loc;
|
||||
/*
|
||||
* Account for the leading Report ID byte
|
||||
* if it is a multi-report device.
|
||||
*/
|
||||
if (hi->id != 0)
|
||||
sc->wheel_loc.pos += 8;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* announce information about the mouse */
|
||||
device_printf(dev, "%d buttons and [%s%s%s%s%s] coordinates ID=%u\n",
|
||||
|
@ -409,7 +409,7 @@ mlx5e_tls_snd_tag_alloc(if_t ifp, union if_snd_tag_alloc_params *params,
|
||||
if (priv->gone != 0 || priv->tls.init == 0)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
ptag = uma_zalloc(priv->tls.zone, M_WAITOK);
|
||||
ptag = uma_zalloc(priv->tls.zone, M_NOWAIT);
|
||||
if (ptag == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
|
@ -3404,6 +3404,51 @@ mlx5e_set_rx_mode(if_t ifp)
|
||||
queue_work(priv->wq, &priv->set_rx_mode_work);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_ipsec_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef IPSEC_OFFLOAD
|
||||
if ((mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD) != 0)
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_ratelimit_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef RATELIMIT
|
||||
if (MLX5_CAP_GEN(mdev, qos) &&
|
||||
MLX5_CAP_QOS(mdev, packet_pacing))
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_tlstx_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef KERN_TLS
|
||||
if (MLX5_CAP_GEN(mdev, tls_tx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0)
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
mlx5e_is_tlsrx_capable(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
#ifdef KERN_TLS
|
||||
if (MLX5_CAP_GEN(mdev, tls_rx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0 &&
|
||||
MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
|
||||
ft_field_support.outer_ip_version) != 0)
|
||||
return (true);
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static int
|
||||
mlx5e_ioctl(if_t ifp, u_long command, caddr_t data)
|
||||
{
|
||||
@ -3507,6 +3552,24 @@ mlx5e_ioctl(if_t ifp, u_long command, caddr_t data)
|
||||
drv_ioctl_data = (struct siocsifcapnv_driver_data *)data;
|
||||
PRIV_LOCK(priv);
|
||||
siocsifcap_driver:
|
||||
if (!mlx5e_is_tlstx_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &= ~(IFCAP_TXTLS4 |
|
||||
IFCAP_TXTLS6);
|
||||
}
|
||||
if (!mlx5e_is_tlsrx_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &= ~(
|
||||
IFCAP2_BIT(IFCAP2_RXTLS4) |
|
||||
IFCAP2_BIT(IFCAP2_RXTLS6));
|
||||
}
|
||||
if (!mlx5e_is_ipsec_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &=
|
||||
~IFCAP2_BIT(IFCAP2_IPSEC_OFFLOAD);
|
||||
}
|
||||
if (!mlx5e_is_ratelimit_capable(priv->mdev)) {
|
||||
drv_ioctl_data->reqcap &= ~(IFCAP_TXTLS_RTLMT |
|
||||
IFCAP_TXRTLMT);
|
||||
}
|
||||
|
||||
mask = drv_ioctl_data->reqcap ^ if_getcapenable(ifp);
|
||||
|
||||
if (mask & IFCAP_TXCSUM) {
|
||||
@ -4535,29 +4598,20 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev)
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TSO | IFCAP_VLAN_HWTSO, 0);
|
||||
if_setcapabilitiesbit(ifp, IFCAP_HWSTATS | IFCAP_HWRXTSTMP, 0);
|
||||
if_setcapabilitiesbit(ifp, IFCAP_MEXTPG, 0);
|
||||
#ifdef KERN_TLS
|
||||
if (MLX5_CAP_GEN(mdev, tls_tx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0)
|
||||
if (mlx5e_is_tlstx_capable(mdev))
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXTLS4 | IFCAP_TXTLS6, 0);
|
||||
if (MLX5_CAP_GEN(mdev, tls_rx) != 0 &&
|
||||
MLX5_CAP_GEN(mdev, log_max_dek) != 0 &&
|
||||
MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
|
||||
ft_field_support.outer_ip_version) != 0)
|
||||
if (mlx5e_is_tlsrx_capable(mdev))
|
||||
if_setcapabilities2bit(ifp, IFCAP2_BIT(IFCAP2_RXTLS4) |
|
||||
IFCAP2_BIT(IFCAP2_RXTLS6), 0);
|
||||
#endif
|
||||
#ifdef RATELIMIT
|
||||
if (MLX5_CAP_GEN(mdev, qos) &&
|
||||
MLX5_CAP_QOS(mdev, packet_pacing))
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXRTLMT | IFCAP_TXTLS_RTLMT,
|
||||
0);
|
||||
#endif
|
||||
if (mlx5e_is_ratelimit_capable(mdev)) {
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXRTLMT, 0);
|
||||
if (mlx5e_is_tlstx_capable(mdev))
|
||||
if_setcapabilitiesbit(ifp, IFCAP_TXTLS_RTLMT, 0);
|
||||
}
|
||||
if_setcapabilitiesbit(ifp, IFCAP_VXLAN_HWCSUM | IFCAP_VXLAN_HWTSO, 0);
|
||||
#ifdef IPSEC_OFFLOAD
|
||||
if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)
|
||||
if (mlx5e_is_ipsec_capable(mdev))
|
||||
if_setcapabilities2bit(ifp, IFCAP2_BIT(IFCAP2_IPSEC_OFFLOAD),
|
||||
0);
|
||||
#endif
|
||||
|
||||
if_setsndtagallocfn(ifp, mlx5e_snd_tag_alloc);
|
||||
#ifdef RATELIMIT
|
||||
|
@ -67,6 +67,24 @@ struct dummy_softc {
|
||||
struct mtx *lock;
|
||||
};
|
||||
|
||||
static bool
|
||||
dummy_active(struct dummy_softc *sc)
|
||||
{
|
||||
struct dummy_chan *ch;
|
||||
int i;
|
||||
|
||||
snd_mtxassert(sc->lock);
|
||||
|
||||
for (i = 0; i < sc->chnum; i++) {
|
||||
ch = &sc->chans[i];
|
||||
if (ch->run)
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* No channel is running at the moment. */
|
||||
return (false);
|
||||
}
|
||||
|
||||
static void
|
||||
dummy_chan_io(void *arg)
|
||||
{
|
||||
@ -74,7 +92,9 @@ dummy_chan_io(void *arg)
|
||||
struct dummy_chan *ch;
|
||||
int i = 0;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
/* Do not reschedule if no channel is running. */
|
||||
if (!dummy_active(sc))
|
||||
return;
|
||||
|
||||
for (i = 0; i < sc->chnum; i++) {
|
||||
ch = &sc->chans[i];
|
||||
@ -89,8 +109,6 @@ dummy_chan_io(void *arg)
|
||||
snd_mtxlock(sc->lock);
|
||||
}
|
||||
callout_schedule(&sc->callout, 1);
|
||||
|
||||
snd_mtxunlock(sc->lock);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -179,15 +197,15 @@ dummy_chan_trigger(kobj_t obj, void *data, int go)
|
||||
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
if (!callout_active(&sc->callout))
|
||||
callout_reset(&sc->callout, 1, dummy_chan_io, sc);
|
||||
ch->ptr = 0;
|
||||
ch->run = 1;
|
||||
callout_reset(&sc->callout, 1, dummy_chan_io, sc);
|
||||
break;
|
||||
case PCMTRIG_STOP:
|
||||
case PCMTRIG_ABORT:
|
||||
ch->run = 0;
|
||||
if (callout_active(&sc->callout))
|
||||
/* If all channels are stopped, stop the callout as well. */
|
||||
if (!dummy_active(sc))
|
||||
callout_stop(&sc->callout);
|
||||
default:
|
||||
break;
|
||||
@ -292,6 +310,7 @@ dummy_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->lock = snd_mtxcreate(device_get_nameunit(dev), "snd_dummy softc");
|
||||
callout_init_mtx(&sc->callout, sc->lock, 0);
|
||||
|
||||
sc->cap_fmts[0] = SND_FORMAT(AFMT_S32_LE, 2, 0);
|
||||
sc->cap_fmts[1] = SND_FORMAT(AFMT_S24_LE, 2, 0);
|
||||
@ -316,7 +335,6 @@ dummy_attach(device_t dev)
|
||||
if (pcm_register(dev, status))
|
||||
return (ENXIO);
|
||||
mixer_init(dev, &dummy_mixer_class, sc);
|
||||
callout_init(&sc->callout, 1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -327,8 +345,8 @@ dummy_detach(device_t dev)
|
||||
struct dummy_softc *sc = device_get_softc(dev);
|
||||
int err;
|
||||
|
||||
callout_drain(&sc->callout);
|
||||
err = pcm_unregister(dev);
|
||||
callout_drain(&sc->callout);
|
||||
snd_mtxfree(sc->lock);
|
||||
|
||||
return (err);
|
||||
|
@ -309,14 +309,7 @@ chn_wakeup(struct pcm_channel *c)
|
||||
if (CHN_EMPTY(c, children.busy)) {
|
||||
if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
|
||||
selwakeuppri(sndbuf_getsel(bs), PRIBIO);
|
||||
if (c->flags & CHN_F_SLEEPING) {
|
||||
/*
|
||||
* Ok, I can just panic it right here since it is
|
||||
* quite obvious that we never allow multiple waiters
|
||||
* from userland. I'm too generous...
|
||||
*/
|
||||
CHN_BROADCAST(&c->intr_cv);
|
||||
}
|
||||
CHN_BROADCAST(&c->intr_cv);
|
||||
} else {
|
||||
CHN_FOREACH(ch, c, children.busy) {
|
||||
CHN_LOCK(ch);
|
||||
@ -332,15 +325,11 @@ chn_sleep(struct pcm_channel *c, int timeout)
|
||||
int ret;
|
||||
|
||||
CHN_LOCKASSERT(c);
|
||||
KASSERT((c->flags & CHN_F_SLEEPING) == 0,
|
||||
("%s(): entered with CHN_F_SLEEPING", __func__));
|
||||
|
||||
if (c->flags & CHN_F_DEAD)
|
||||
return (EINVAL);
|
||||
|
||||
c->flags |= CHN_F_SLEEPING;
|
||||
ret = cv_timedwait_sig(&c->intr_cv, c->lock, timeout);
|
||||
c->flags &= ~CHN_F_SLEEPING;
|
||||
|
||||
return ((c->flags & CHN_F_DEAD) ? EINVAL : ret);
|
||||
}
|
||||
@ -2318,44 +2307,46 @@ chn_trigger(struct pcm_channel *c, int go)
|
||||
if (go == c->trigger)
|
||||
return (0);
|
||||
|
||||
if (snd_verbose > 3) {
|
||||
device_printf(c->dev, "%s() %s: calling go=0x%08x , "
|
||||
"prev=0x%08x\n", __func__, c->name, go, c->trigger);
|
||||
}
|
||||
|
||||
c->trigger = go;
|
||||
ret = CHANNEL_TRIGGER(c->methods, c->devinfo, go);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
CHN_UNLOCK(c);
|
||||
PCM_LOCK(d);
|
||||
CHN_LOCK(c);
|
||||
|
||||
/*
|
||||
* Do nothing if another thread set a different trigger while we had
|
||||
* dropped the mutex.
|
||||
*/
|
||||
if (go != c->trigger) {
|
||||
PCM_UNLOCK(d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the SAFE variants to prevent inserting/removing an already
|
||||
* existing/missing element.
|
||||
*/
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
if (snd_verbose > 3)
|
||||
device_printf(c->dev,
|
||||
"%s() %s: calling go=0x%08x , "
|
||||
"prev=0x%08x\n", __func__, c->name, go,
|
||||
c->trigger);
|
||||
if (c->trigger != PCMTRIG_START) {
|
||||
c->trigger = go;
|
||||
CHN_UNLOCK(c);
|
||||
PCM_LOCK(d);
|
||||
CHN_INSERT_HEAD(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
CHN_LOCK(c);
|
||||
chn_syncstate(c);
|
||||
}
|
||||
CHN_INSERT_HEAD_SAFE(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
chn_syncstate(c);
|
||||
break;
|
||||
case PCMTRIG_STOP:
|
||||
case PCMTRIG_ABORT:
|
||||
if (snd_verbose > 3)
|
||||
device_printf(c->dev,
|
||||
"%s() %s: calling go=0x%08x , "
|
||||
"prev=0x%08x\n", __func__, c->name, go,
|
||||
c->trigger);
|
||||
if (c->trigger == PCMTRIG_START) {
|
||||
c->trigger = go;
|
||||
CHN_UNLOCK(c);
|
||||
PCM_LOCK(d);
|
||||
CHN_REMOVE(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
CHN_LOCK(c);
|
||||
}
|
||||
CHN_REMOVE_SAFE(d, c, channels.pcm.busy);
|
||||
PCM_UNLOCK(d);
|
||||
break;
|
||||
default:
|
||||
PCM_UNLOCK(d);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ enum {
|
||||
#define CHN_F_RUNNING 0x00000004 /* dma is running */
|
||||
#define CHN_F_TRIGGERED 0x00000008
|
||||
#define CHN_F_NOTRIGGER 0x00000010
|
||||
#define CHN_F_SLEEPING 0x00000020
|
||||
/* unused 0x00000020 */
|
||||
|
||||
#define CHN_F_NBIO 0x00000040 /* do non-blocking i/o */
|
||||
#define CHN_F_MMAP 0x00000080 /* has been mmap()ed */
|
||||
@ -362,7 +362,7 @@ enum {
|
||||
#define CHN_F_BUSY 0x00000100 /* has been opened */
|
||||
#define CHN_F_DIRTY 0x00000200 /* need re-config */
|
||||
#define CHN_F_DEAD 0x00000400 /* too many errors, dead, mdk */
|
||||
#define CHN_F_SILENCE 0x00000800 /* silence, nil, null, yada */
|
||||
/* unused 0x00000800 */
|
||||
|
||||
#define CHN_F_HAS_SIZE 0x00001000 /* user set block size */
|
||||
#define CHN_F_HAS_VCHAN 0x00002000 /* vchan master */
|
||||
@ -381,14 +381,14 @@ enum {
|
||||
"\002ABORTING" \
|
||||
"\003RUNNING" \
|
||||
"\004TRIGGERED" \
|
||||
/* \006 */ \
|
||||
"\005NOTRIGGER" \
|
||||
"\006SLEEPING" \
|
||||
"\007NBIO" \
|
||||
"\010MMAP" \
|
||||
"\011BUSY" \
|
||||
"\012DIRTY" \
|
||||
"\013DEAD" \
|
||||
"\014SILENCE" \
|
||||
/* \014 */ \
|
||||
"\015HAS_SIZE" \
|
||||
"\016HAS_VCHAN" \
|
||||
"\017VCHAN_PASSTHROUGH" \
|
||||
|
@ -137,7 +137,7 @@ dsp_destroy_dev(device_t dev)
|
||||
struct snddev_info *d;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
destroy_dev_sched(d->dsp_dev);
|
||||
destroy_dev(d->dsp_dev);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -177,7 +177,7 @@ dsp_close(void *data)
|
||||
|
||||
d = priv->sc;
|
||||
/* At this point pcm_unregister() will destroy all channels anyway. */
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
goto skip;
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -264,7 +264,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
||||
return (ENODEV);
|
||||
|
||||
d = i_dev->si_drv1;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
@ -445,7 +445,7 @@ dsp_io_ops(struct dsp_cdevpriv *priv, struct uio *buf)
|
||||
("%s(): io train wreck!", __func__));
|
||||
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -664,7 +664,7 @@ dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
|
||||
return (err);
|
||||
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -1783,7 +1783,7 @@ dsp_poll(struct cdev *i_dev, int events, struct thread *td)
|
||||
if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
|
||||
return (err);
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d)) {
|
||||
if (!DSP_REGISTERED(d)) {
|
||||
/* XXX many clients don't understand POLLNVAL */
|
||||
return (events & (POLLHUP | POLLPRI | POLLIN |
|
||||
POLLRDNORM | POLLOUT | POLLWRNORM));
|
||||
@ -1865,7 +1865,7 @@ dsp_mmap_single(struct cdev *i_dev, vm_ooffset_t *offset,
|
||||
if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
|
||||
return (err);
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EINVAL);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
|
@ -146,7 +146,7 @@ mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
|
||||
struct pcm_channel *c;
|
||||
int dropmtx, acquiremtx;
|
||||
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EINVAL);
|
||||
|
||||
if (mtx_owned(m->lock))
|
||||
@ -199,7 +199,7 @@ mixer_set_eq(struct snd_mixer *m, struct snddev_info *d,
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EINVAL);
|
||||
|
||||
if (mtx_owned(m->lock))
|
||||
@ -1053,7 +1053,7 @@ mixer_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
||||
|
||||
m = i_dev->si_drv1;
|
||||
d = device_get_softc(m->dev);
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
/* XXX Need Giant magic entry ??? */
|
||||
@ -1209,7 +1209,7 @@ mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
|
||||
return (EBADF);
|
||||
|
||||
d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d))
|
||||
if (!PCM_REGISTERED(d))
|
||||
return (EBADF);
|
||||
|
||||
PCM_GIANT_ENTER(d);
|
||||
@ -1447,7 +1447,7 @@ mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
|
||||
for (i = 0; pcm_devclass != NULL &&
|
||||
i < devclass_get_maxunit(pcm_devclass); i++) {
|
||||
d = devclass_get_softc(pcm_devclass, i);
|
||||
if (!PCM_REGISTERED(d) || PCM_DETACHING(d)) {
|
||||
if (!PCM_REGISTERED(d)) {
|
||||
if ((mi->dev == -1 && i == snd_unit) || mi->dev == i) {
|
||||
mixer_oss_mixerinfo_unavail(mi, i);
|
||||
return (0);
|
||||
|
@ -211,40 +211,53 @@ static void
|
||||
pcm_killchans(struct snddev_info *d)
|
||||
{
|
||||
struct pcm_channel *ch;
|
||||
bool found;
|
||||
bool again;
|
||||
|
||||
PCM_BUSYASSERT(d);
|
||||
do {
|
||||
found = false;
|
||||
KASSERT(!PCM_REGISTERED(d), ("%s(): still registered\n", __func__));
|
||||
|
||||
for (;;) {
|
||||
again = false;
|
||||
/* Make sure all channels are stopped. */
|
||||
CHN_FOREACH(ch, d, channels.pcm) {
|
||||
CHN_LOCK(ch);
|
||||
/*
|
||||
* Make sure no channel has went to sleep in the
|
||||
* meantime.
|
||||
*/
|
||||
chn_shutdown(ch);
|
||||
/*
|
||||
* We have to give a thread sleeping in chn_sleep() a
|
||||
* chance to observe that the channel is dead.
|
||||
*/
|
||||
if ((ch->flags & CHN_F_SLEEPING) == 0) {
|
||||
found = true;
|
||||
if (ch->intr_cv.cv_waiters == 0 && CHN_STOPPED(ch) &&
|
||||
ch->inprog == 0) {
|
||||
CHN_UNLOCK(ch);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
chn_shutdown(ch);
|
||||
if (ch->direction == PCMDIR_PLAY)
|
||||
chn_flush(ch);
|
||||
else
|
||||
chn_abort(ch);
|
||||
CHN_UNLOCK(ch);
|
||||
again = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* All channels are still sleeping. Sleep for a bit and try
|
||||
* again to see if any of them is awake now.
|
||||
* Some channels are still active. Sleep for a bit and try
|
||||
* again.
|
||||
*/
|
||||
if (!found) {
|
||||
pause_sbt("pcmkillchans", SBT_1MS * 5, 0, 0);
|
||||
continue;
|
||||
}
|
||||
if (again)
|
||||
pause_sbt("pcmkillchans", mstosbt(5), 0, 0);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* All channels are finally dead. */
|
||||
while (!CHN_EMPTY(d, channels.pcm)) {
|
||||
ch = CHN_FIRST(d, channels.pcm);
|
||||
chn_kill(ch);
|
||||
} while (!CHN_EMPTY(d, channels.pcm));
|
||||
}
|
||||
|
||||
if (d->p_unr != NULL)
|
||||
delete_unrhdr(d->p_unr);
|
||||
if (d->vp_unr != NULL)
|
||||
delete_unrhdr(d->vp_unr);
|
||||
if (d->r_unr != NULL)
|
||||
delete_unrhdr(d->r_unr);
|
||||
if (d->vr_unr != NULL)
|
||||
delete_unrhdr(d->vr_unr);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -512,7 +525,6 @@ int
|
||||
pcm_unregister(device_t dev)
|
||||
{
|
||||
struct snddev_info *d;
|
||||
struct pcm_channel *ch;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
|
||||
@ -524,29 +536,14 @@ pcm_unregister(device_t dev)
|
||||
PCM_LOCK(d);
|
||||
PCM_WAIT(d);
|
||||
|
||||
d->flags |= SD_F_DETACHING;
|
||||
d->flags &= ~SD_F_REGISTERED;
|
||||
|
||||
PCM_ACQUIRE(d);
|
||||
PCM_UNLOCK(d);
|
||||
|
||||
CHN_FOREACH(ch, d, channels.pcm) {
|
||||
CHN_LOCK(ch);
|
||||
/*
|
||||
* Do not wait for the timeout in chn_read()/chn_write(). Wake
|
||||
* up the sleeping thread and kill the channel.
|
||||
*/
|
||||
chn_shutdown(ch);
|
||||
chn_abort(ch);
|
||||
CHN_UNLOCK(ch);
|
||||
}
|
||||
pcm_killchans(d);
|
||||
|
||||
/* remove /dev/sndstat entry first */
|
||||
sndstat_unregister(dev);
|
||||
|
||||
PCM_LOCK(d);
|
||||
d->flags |= SD_F_DYING;
|
||||
d->flags &= ~SD_F_REGISTERED;
|
||||
PCM_UNLOCK(d);
|
||||
PCM_RELEASE_QUICK(d);
|
||||
|
||||
if (d->play_sysctl_tree != NULL) {
|
||||
sysctl_ctx_free(&d->play_sysctl_ctx);
|
||||
@ -557,24 +554,12 @@ pcm_unregister(device_t dev)
|
||||
d->rec_sysctl_tree = NULL;
|
||||
}
|
||||
|
||||
sndstat_unregister(dev);
|
||||
mixer_uninit(dev);
|
||||
dsp_destroy_dev(dev);
|
||||
(void)mixer_uninit(dev);
|
||||
|
||||
pcm_killchans(d);
|
||||
|
||||
PCM_LOCK(d);
|
||||
PCM_RELEASE(d);
|
||||
cv_destroy(&d->cv);
|
||||
PCM_UNLOCK(d);
|
||||
snd_mtxfree(d->lock);
|
||||
if (d->p_unr != NULL)
|
||||
delete_unrhdr(d->p_unr);
|
||||
if (d->vp_unr != NULL)
|
||||
delete_unrhdr(d->vp_unr);
|
||||
if (d->r_unr != NULL)
|
||||
delete_unrhdr(d->r_unr);
|
||||
if (d->vr_unr != NULL)
|
||||
delete_unrhdr(d->vr_unr);
|
||||
|
||||
if (snd_unit == device_get_unit(dev)) {
|
||||
snd_unit = pcm_best_unit(-1);
|
||||
|
@ -104,17 +104,15 @@ struct snd_mixer;
|
||||
#define SD_F_SIMPLEX 0x00000001
|
||||
#define SD_F_AUTOVCHAN 0x00000002
|
||||
#define SD_F_SOFTPCMVOL 0x00000004
|
||||
#define SD_F_DYING 0x00000008
|
||||
#define SD_F_DETACHING 0x00000010
|
||||
#define SD_F_BUSY 0x00000020
|
||||
#define SD_F_MPSAFE 0x00000040
|
||||
#define SD_F_REGISTERED 0x00000080
|
||||
#define SD_F_BITPERFECT 0x00000100
|
||||
#define SD_F_VPC 0x00000200 /* volume-per-channel */
|
||||
#define SD_F_EQ 0x00000400 /* EQ */
|
||||
#define SD_F_EQ_ENABLED 0x00000800 /* EQ enabled */
|
||||
#define SD_F_EQ_BYPASSED 0x00001000 /* EQ bypassed */
|
||||
#define SD_F_EQ_PC 0x00002000 /* EQ per-channel */
|
||||
#define SD_F_BUSY 0x00000008
|
||||
#define SD_F_MPSAFE 0x00000010
|
||||
#define SD_F_REGISTERED 0x00000020
|
||||
#define SD_F_BITPERFECT 0x00000040
|
||||
#define SD_F_VPC 0x00000080 /* volume-per-channel */
|
||||
#define SD_F_EQ 0x00000100 /* EQ */
|
||||
#define SD_F_EQ_ENABLED 0x00000200 /* EQ enabled */
|
||||
#define SD_F_EQ_BYPASSED 0x00000400 /* EQ bypassed */
|
||||
#define SD_F_EQ_PC 0x00000800 /* EQ per-channel */
|
||||
|
||||
#define SD_F_EQ_DEFAULT (SD_F_EQ | SD_F_EQ_ENABLED)
|
||||
#define SD_F_EQ_MASK (SD_F_EQ | SD_F_EQ_ENABLED | \
|
||||
@ -127,26 +125,20 @@ struct snd_mixer;
|
||||
"\001SIMPLEX" \
|
||||
"\002AUTOVCHAN" \
|
||||
"\003SOFTPCMVOL" \
|
||||
"\004DYING" \
|
||||
"\005DETACHING" \
|
||||
"\006BUSY" \
|
||||
"\007MPSAFE" \
|
||||
"\010REGISTERED" \
|
||||
"\011BITPERFECT" \
|
||||
"\012VPC" \
|
||||
"\013EQ" \
|
||||
"\014EQ_ENABLED" \
|
||||
"\015EQ_BYPASSED" \
|
||||
"\016EQ_PC" \
|
||||
"\004BUSY" \
|
||||
"\005MPSAFE" \
|
||||
"\006REGISTERED" \
|
||||
"\007BITPERFECT" \
|
||||
"\010VPC" \
|
||||
"\011EQ" \
|
||||
"\012EQ_ENABLED" \
|
||||
"\013EQ_BYPASSED" \
|
||||
"\014EQ_PC" \
|
||||
"\035PRIO_RD" \
|
||||
"\036PRIO_WR"
|
||||
|
||||
#define PCM_ALIVE(x) ((x) != NULL && (x)->lock != NULL && \
|
||||
!((x)->flags & SD_F_DYING))
|
||||
#define PCM_REGISTERED(x) (PCM_ALIVE(x) && \
|
||||
((x)->flags & SD_F_REGISTERED))
|
||||
|
||||
#define PCM_DETACHING(x) ((x)->flags & SD_F_DETACHING)
|
||||
#define PCM_ALIVE(x) ((x) != NULL && (x)->lock != NULL)
|
||||
#define PCM_REGISTERED(x) (PCM_ALIVE(x) && ((x)->flags & SD_F_REGISTERED))
|
||||
|
||||
#define PCM_CHANCOUNT(d) \
|
||||
(d->playcount + d->pvchancount + d->reccount + d->rvchancount)
|
||||
|
@ -146,20 +146,19 @@ vchan_trigger(kobj_t obj, void *data, int go)
|
||||
int ret, otrigger;
|
||||
|
||||
info = data;
|
||||
c = info->channel;
|
||||
p = c->parentchannel;
|
||||
|
||||
CHN_LOCKASSERT(c);
|
||||
if (!PCMTRIG_COMMON(go) || go == info->trigger)
|
||||
return (0);
|
||||
|
||||
c = info->channel;
|
||||
p = c->parentchannel;
|
||||
otrigger = info->trigger;
|
||||
info->trigger = go;
|
||||
|
||||
CHN_LOCKASSERT(c);
|
||||
|
||||
CHN_UNLOCK(c);
|
||||
CHN_LOCK(p);
|
||||
|
||||
otrigger = info->trigger;
|
||||
info->trigger = go;
|
||||
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
if (otrigger != PCMTRIG_START)
|
||||
|
@ -365,6 +365,16 @@ sigqueue_start(void)
|
||||
SIGFILLSET(fastblock_mask);
|
||||
SIG_CANTMASK(fastblock_mask);
|
||||
ast_register(TDA_SIG, ASTR_UNCOND, 0, ast_sig);
|
||||
|
||||
/*
|
||||
* TDA_PSELECT is for the case where the signal mask should be restored
|
||||
* before delivering any signals so that we do not deliver any that are
|
||||
* blocked by the normal thread mask. It is mutually exclusive with
|
||||
* TDA_SIGSUSPEND, which should be used if we *do* want to deliver
|
||||
* signals that are normally blocked, e.g., if it interrupted our sleep.
|
||||
*/
|
||||
ast_register(TDA_PSELECT, ASTR_ASTF_REQUIRED | ASTR_TDP,
|
||||
TDP_OLDMASK, ast_sigsuspend);
|
||||
ast_register(TDA_SIGSUSPEND, ASTR_ASTF_REQUIRED | ASTR_TDP,
|
||||
TDP_OLDMASK, ast_sigsuspend);
|
||||
}
|
||||
|
@ -133,8 +133,10 @@ livedump_start_vnode(struct vnode *vp, int flags, uint8_t compression)
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
curthread->td_pflags2 |= TDP2_SAN_QUIET;
|
||||
dump_savectx();
|
||||
error = minidumpsys(livedi, true);
|
||||
curthread->td_pflags2 &= ~TDP2_SAN_QUIET;
|
||||
|
||||
EVENTHANDLER_INVOKE(livedumper_finish);
|
||||
out:
|
||||
|
@ -405,6 +405,9 @@ kasan_shadow_check(unsigned long addr, size_t size, bool write,
|
||||
|
||||
if (__predict_false(!kasan_enabled))
|
||||
return;
|
||||
if (__predict_false(curthread != NULL &&
|
||||
(curthread->td_pflags2 & TDP2_SAN_QUIET) != 0))
|
||||
return;
|
||||
if (__predict_false(size == 0))
|
||||
return;
|
||||
if (__predict_false(kasan_md_unsupported(addr)))
|
||||
|
@ -179,6 +179,9 @@ kmsan_report_hook(const void *addr, msan_orig_t *orig, size_t size, size_t off,
|
||||
|
||||
if (__predict_false(KERNEL_PANICKED() || kdb_active || kmsan_reporting))
|
||||
return;
|
||||
if (__predict_false(curthread != NULL &&
|
||||
(curthread->td_pflags2 & TDP2_SAN_QUIET) != 0))
|
||||
return;
|
||||
|
||||
kmsan_reporting = true;
|
||||
__compiler_membar();
|
||||
@ -232,6 +235,9 @@ kmsan_report_inline(msan_orig_t orig, unsigned long pc)
|
||||
|
||||
if (__predict_false(KERNEL_PANICKED() || kdb_active || kmsan_reporting))
|
||||
return;
|
||||
if (__predict_false(curthread != NULL &&
|
||||
(curthread->td_pflags2 & TDP2_SAN_QUIET) != 0))
|
||||
return;
|
||||
|
||||
kmsan_reporting = true;
|
||||
__compiler_membar();
|
||||
|
@ -1049,14 +1049,26 @@ kern_pselect(struct thread *td, int nd, fd_set *in, fd_set *ou, fd_set *ex,
|
||||
if (error != 0)
|
||||
return (error);
|
||||
td->td_pflags |= TDP_OLDMASK;
|
||||
}
|
||||
error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits);
|
||||
if (uset != NULL) {
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
* usermode and TDP_OLDMASK is cleared, restoring old
|
||||
* sigmask.
|
||||
* sigmask. If we didn't get interrupted, then the caller is
|
||||
* likely not expecting a signal to hit that should normally be
|
||||
* blocked by its signal mask, so we restore the mask before
|
||||
* any signals could be delivered.
|
||||
*/
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
if (error == EINTR) {
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
} else {
|
||||
/* *select(2) should never restart. */
|
||||
MPASS(error != ERESTART);
|
||||
ast_sched(td, TDA_PSELECT);
|
||||
}
|
||||
}
|
||||
error = kern_select(td, nd, in, ou, ex, tvp, abi_nfdbits);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1528,12 +1540,6 @@ kern_poll_kfds(struct thread *td, struct pollfd *kfds, u_int nfds,
|
||||
if (error)
|
||||
return (error);
|
||||
td->td_pflags |= TDP_OLDMASK;
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
* usermode and TDP_OLDMASK is cleared, restoring old
|
||||
* sigmask.
|
||||
*/
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
}
|
||||
|
||||
seltdinit(td);
|
||||
@ -1556,6 +1562,22 @@ kern_poll_kfds(struct thread *td, struct pollfd *kfds, u_int nfds,
|
||||
error = EINTR;
|
||||
if (error == EWOULDBLOCK)
|
||||
error = 0;
|
||||
|
||||
if (uset != NULL) {
|
||||
/*
|
||||
* Make sure that ast() is called on return to
|
||||
* usermode and TDP_OLDMASK is cleared, restoring old
|
||||
* sigmask. If we didn't get interrupted, then the caller is
|
||||
* likely not expecting a signal to hit that should normally be
|
||||
* blocked by its signal mask, so we restore the mask before
|
||||
* any signals could be delivered.
|
||||
*/
|
||||
if (error == EINTR)
|
||||
ast_sched(td, TDA_SIGSUSPEND);
|
||||
else
|
||||
ast_sched(td, TDA_PSELECT);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ SYSCTL_UINT(_kern_ipc_tls, OID_AUTO, ifnet_max_rexmit_pct, CTLFLAG_RWTUN,
|
||||
&ktls_ifnet_max_rexmit_pct, 2,
|
||||
"Max percent bytes retransmitted before ifnet TLS is disabled");
|
||||
|
||||
static bool ktls_offload_enable;
|
||||
static bool ktls_offload_enable = true;
|
||||
SYSCTL_BOOL(_kern_ipc_tls, OID_AUTO, enable, CTLFLAG_RWTUN,
|
||||
&ktls_offload_enable, 0,
|
||||
"Enable support for kernel TLS offload");
|
||||
@ -273,7 +273,7 @@ SYSCTL_COUNTER_U64(_kern_ipc_tls_ifnet, OID_AUTO, reset_failed, CTLFLAG_RD,
|
||||
&ktls_ifnet_reset_failed,
|
||||
"TLS sessions that failed to allocate a new ifnet send tag");
|
||||
|
||||
static int ktls_ifnet_permitted;
|
||||
static int ktls_ifnet_permitted = 1;
|
||||
SYSCTL_UINT(_kern_ipc_tls_ifnet, OID_AUTO, permitted, CTLFLAG_RWTUN,
|
||||
&ktls_ifnet_permitted, 1,
|
||||
"Whether to permit hardware (ifnet) TLS sessions");
|
||||
|
@ -3265,6 +3265,8 @@ kern___realpathat(struct thread *td, int fd, const char *path, char *buf,
|
||||
|
||||
if (nd.ni_vp->v_type == VREG && nd.ni_dvp->v_type != VDIR &&
|
||||
(nd.ni_vp->v_vflag & VV_ROOT) != 0) {
|
||||
struct vnode *covered_vp;
|
||||
|
||||
/*
|
||||
* This happens if vp is a file mount. The call to
|
||||
* vn_fullpath_hardlink can panic if path resolution can't be
|
||||
@ -3274,7 +3276,6 @@ kern___realpathat(struct thread *td, int fd, const char *path, char *buf,
|
||||
* this should have a unique global path since we disallow
|
||||
* mounting on linked files.
|
||||
*/
|
||||
struct vnode *covered_vp;
|
||||
error = vn_lock(nd.ni_vp, LK_SHARED);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
@ -3284,11 +3285,20 @@ kern___realpathat(struct thread *td, int fd, const char *path, char *buf,
|
||||
error = vn_fullpath(covered_vp, &retbuf, &freebuf);
|
||||
vrele(covered_vp);
|
||||
} else {
|
||||
error = vn_fullpath_hardlink(nd.ni_vp, nd.ni_dvp, nd.ni_cnd.cn_nameptr,
|
||||
nd.ni_cnd.cn_namelen, &retbuf, &freebuf, &size);
|
||||
error = vn_fullpath_hardlink(nd.ni_vp, nd.ni_dvp,
|
||||
nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen, &retbuf,
|
||||
&freebuf, &size);
|
||||
}
|
||||
if (error == 0) {
|
||||
error = copyout(retbuf, buf, size);
|
||||
size_t len;
|
||||
|
||||
len = strlen(retbuf) + 1;
|
||||
if (size < len)
|
||||
error = ENAMETOOLONG;
|
||||
else if (pathseg == UIO_USERSPACE)
|
||||
error = copyout(retbuf, buf, len);
|
||||
else
|
||||
memcpy(buf, retbuf, len);
|
||||
free(freebuf, M_TEMP);
|
||||
}
|
||||
out:
|
||||
|
@ -70,6 +70,8 @@
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define PF_PFIL_NOREFRAGMENT 0x80000000
|
||||
|
||||
#if defined(__arm__)
|
||||
#define PF_WANT_32_TO_64_COUNTER
|
||||
#endif
|
||||
@ -2372,7 +2374,8 @@ void pf_poolmask(struct pf_addr *, struct pf_addr*,
|
||||
struct pf_addr *, struct pf_addr *, sa_family_t);
|
||||
void pf_addr_inc(struct pf_addr *, sa_family_t);
|
||||
int pf_max_frag_size(struct mbuf *);
|
||||
int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *, bool);
|
||||
int pf_refragment6(struct ifnet *, struct mbuf **, struct m_tag *,
|
||||
struct ifnet *, bool);
|
||||
#endif /* INET6 */
|
||||
|
||||
int pf_multihome_scan_init(int, int, struct pf_pdesc *);
|
||||
|
@ -1112,7 +1112,7 @@ ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
|
||||
#endif
|
||||
struct ip *ip;
|
||||
#ifdef INET
|
||||
int setdf;
|
||||
int setdf = V_ip4_ipsec_dfbit == 1 ? 1: 0;
|
||||
#endif
|
||||
uint8_t itos, proto;
|
||||
|
||||
@ -1122,17 +1122,11 @@ ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
|
||||
case IPVERSION:
|
||||
proto = IPPROTO_IPIP;
|
||||
/*
|
||||
* Collect IP_DF state from the inner header
|
||||
* and honor system-wide control of how to handle it.
|
||||
* Copy IP_DF flag from the inner header if
|
||||
* system-wide control variable is greater than 1.
|
||||
*/
|
||||
switch (V_ip4_ipsec_dfbit) {
|
||||
case 0: /* clear in outer header */
|
||||
case 1: /* set in outer header */
|
||||
setdf = V_ip4_ipsec_dfbit;
|
||||
break;
|
||||
default:/* propagate to outer header */
|
||||
if (V_ip4_ipsec_dfbit > 1)
|
||||
setdf = (ip->ip_off & htons(IP_DF)) != 0;
|
||||
}
|
||||
itos = ip->ip_tos;
|
||||
break;
|
||||
#endif
|
||||
|
@ -7927,6 +7927,7 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
struct pf_kstate *s, struct pf_pdesc *pd, struct inpcb *inp)
|
||||
{
|
||||
struct mbuf *m0, *md;
|
||||
struct m_tag *mtag;
|
||||
struct sockaddr_in6 dst;
|
||||
struct ip6_hdr *ip6;
|
||||
struct pfi_kkif *nkif = NULL;
|
||||
@ -8053,8 +8054,8 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
}
|
||||
|
||||
if (pd->dir == PF_IN) {
|
||||
if (pf_test(AF_INET6, PF_OUT, PFIL_FWD, ifp, &m0, inp,
|
||||
&pd->act) != PF_PASS) {
|
||||
if (pf_test(AF_INET6, PF_OUT, PFIL_FWD | PF_PFIL_NOREFRAGMENT,
|
||||
ifp, &m0, inp, &pd->act) != PF_PASS) {
|
||||
SDT_PROBE1(pf, ip6, route_to, drop, __LINE__);
|
||||
goto bad;
|
||||
} else if (m0 == NULL) {
|
||||
@ -8087,6 +8088,14 @@ pf_route6(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp,
|
||||
*/
|
||||
if (IN6_IS_SCOPE_EMBED(&dst.sin6_addr))
|
||||
dst.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
mtag = m_tag_find(m0, PACKET_TAG_PF_REASSEMBLED, NULL);
|
||||
if (mtag != NULL) {
|
||||
int ret;
|
||||
ret = pf_refragment6(ifp, &m0, mtag, ifp, true);
|
||||
SDT_PROBE2(pf, ip6, route_to, output, ifp, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
|
||||
md = m0;
|
||||
pf_dummynet_route(pd, s, r, ifp, sintosa(&dst), &md);
|
||||
@ -9474,14 +9483,15 @@ eat_pkt:
|
||||
if (s)
|
||||
PF_STATE_UNLOCK(s);
|
||||
|
||||
out:
|
||||
#ifdef INET6
|
||||
/* If reassembled packet passed, create new fragments. */
|
||||
if (af == AF_INET6 && action == PF_PASS && *m0 && dir == PF_OUT &&
|
||||
(! (pflags & PF_PFIL_NOREFRAGMENT)) &&
|
||||
(mtag = m_tag_find(pd.m, PACKET_TAG_PF_REASSEMBLED, NULL)) != NULL)
|
||||
action = pf_refragment6(ifp, m0, mtag, pflags & PFIL_FWD);
|
||||
action = pf_refragment6(ifp, m0, mtag, NULL, pflags & PFIL_FWD);
|
||||
#endif
|
||||
|
||||
out:
|
||||
pf_sctp_multihome_delayed(&pd, kif, s, action);
|
||||
|
||||
return (action);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/vnet.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <net/if_pflog.h>
|
||||
@ -49,6 +50,8 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
#include <netinet/tcp.h>
|
||||
@ -958,7 +961,7 @@ pf_max_frag_size(struct mbuf *m)
|
||||
|
||||
int
|
||||
pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
|
||||
bool forward)
|
||||
struct ifnet *rt, bool forward)
|
||||
{
|
||||
struct mbuf *m = *m0, *t;
|
||||
struct ip6_hdr *hdr;
|
||||
@ -1029,16 +1032,27 @@ pf_refragment6(struct ifnet *ifp, struct mbuf **m0, struct m_tag *mtag,
|
||||
m->m_flags |= M_SKIP_FIREWALL;
|
||||
memset(&pd, 0, sizeof(pd));
|
||||
pd.pf_mtag = pf_find_mtag(m);
|
||||
if (error == 0)
|
||||
if (forward) {
|
||||
MPASS(m->m_pkthdr.rcvif != NULL);
|
||||
ip6_forward(m, 0);
|
||||
} else {
|
||||
(void)ip6_output(m, NULL, NULL, 0, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
if (error != 0) {
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
if (rt != NULL) {
|
||||
struct sockaddr_in6 dst;
|
||||
hdr = mtod(m, struct ip6_hdr *);
|
||||
|
||||
bzero(&dst, sizeof(dst));
|
||||
dst.sin6_family = AF_INET6;
|
||||
dst.sin6_len = sizeof(dst);
|
||||
dst.sin6_addr = hdr->ip6_dst;
|
||||
|
||||
nd6_output_ifp(rt, rt, m, &dst, NULL);
|
||||
} else if (forward) {
|
||||
MPASS(m->m_pkthdr.rcvif != NULL);
|
||||
ip6_forward(m, 0);
|
||||
} else {
|
||||
(void)ip6_output(m, NULL, NULL, 0, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (action);
|
||||
|
@ -69,4 +69,9 @@
|
||||
li tmp, SSTATUS_SUM; \
|
||||
csrc sstatus, tmp
|
||||
|
||||
#define SBI_CALL(ext, func) \
|
||||
li a7, ext; \
|
||||
li a6, func; \
|
||||
ecall
|
||||
|
||||
#endif /* _MACHINE_ASM_H_ */
|
||||
|
@ -35,9 +35,11 @@
|
||||
#ifndef _MACHINE_CPU_H_
|
||||
#define _MACHINE_CPU_H_
|
||||
|
||||
#ifndef LOCORE
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/frame.h>
|
||||
#endif
|
||||
|
||||
#define TRAPF_PC(tfp) ((tfp)->tf_sepc)
|
||||
#define TRAPF_USERMODE(tfp) (((tfp)->tf_sstatus & SSTATUS_SPP) == 0)
|
||||
@ -88,6 +90,7 @@
|
||||
#define MMU_SV57 0x4 /* 5-level paging */
|
||||
|
||||
#ifdef _KERNEL
|
||||
#ifndef LOCORE
|
||||
|
||||
extern char btext[];
|
||||
extern char etext[];
|
||||
@ -105,6 +108,7 @@ get_cyclecount(void)
|
||||
return (rdcycle());
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* !LOCORE */
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_MACHINE_CPU_H_ */
|
||||
|
@ -44,6 +44,8 @@ breakpoint(void)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/_null.h>
|
||||
|
||||
#include <machine/riscvreg.h>
|
||||
|
||||
static __inline register_t
|
||||
@ -107,16 +109,42 @@ sfence_vma_page(uintptr_t addr)
|
||||
#define rdinstret() csr_read64(instret)
|
||||
#define rdhpmcounter(n) csr_read64(hpmcounter##n)
|
||||
|
||||
/* Cache hooks. */
|
||||
|
||||
extern int64_t dcache_line_size;
|
||||
extern int64_t icache_line_size;
|
||||
|
||||
#define cpu_dcache_wbinv_range(a, s)
|
||||
#define cpu_dcache_inv_range(a, s)
|
||||
#define cpu_dcache_wb_range(a, s)
|
||||
typedef void (*cache_op_t)(vm_offset_t start, vm_size_t size);
|
||||
|
||||
#define cpu_idcache_wbinv_range(a, s)
|
||||
#define cpu_icache_sync_range(a, s)
|
||||
#define cpu_icache_sync_range_checked(a, s)
|
||||
struct riscv_cache_ops {
|
||||
cache_op_t dcache_wbinv_range;
|
||||
cache_op_t dcache_inv_range;
|
||||
cache_op_t dcache_wb_range;
|
||||
};
|
||||
|
||||
extern struct riscv_cache_ops cache_ops;
|
||||
|
||||
static __inline void
|
||||
cpu_dcache_wbinv_range(vm_offset_t addr, vm_size_t size)
|
||||
{
|
||||
if (cache_ops.dcache_wbinv_range != NULL)
|
||||
cache_ops.dcache_wbinv_range(addr, size);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cpu_dcache_inv_range(vm_offset_t addr, vm_size_t size)
|
||||
{
|
||||
if (cache_ops.dcache_inv_range != NULL)
|
||||
cache_ops.dcache_inv_range(addr, size);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cpu_dcache_wb_range(vm_offset_t addr, vm_size_t size)
|
||||
{
|
||||
if (cache_ops.dcache_wb_range != NULL)
|
||||
cache_ops.dcache_wb_range(addr, size);
|
||||
}
|
||||
|
||||
void riscv_cache_install_hooks(struct riscv_cache_ops *, u_int);
|
||||
|
||||
#define cpufunc_nullop() riscv_nullop()
|
||||
|
||||
|
@ -102,6 +102,32 @@ typedef uint64_t pn_t; /* page number */
|
||||
#define PTE_MA_NC (1ul << PTE_MA_SHIFT)
|
||||
#define PTE_MA_IO (2ul << PTE_MA_SHIFT)
|
||||
|
||||
/*
|
||||
* T-HEAD Custom Memory Attribute (MA) bits [63:59].
|
||||
*
|
||||
* bit 59: Trustable (relating to TEE)
|
||||
* bit 60: Shareable (among CPUs, not configurable)
|
||||
* bit 61: Bufferable (writes to device memory)
|
||||
* bit 62: Cacheable
|
||||
* bit 63: Memory Ordering (1 = strongly ordered (device), 0 = default)
|
||||
*
|
||||
* +------+-------+------------------------------------------------------------+
|
||||
* | Mode | Value | Requested Memory Attributes |
|
||||
* +------+-------+------------------------------------------------------------+
|
||||
* | NC | 00110 | Weakly-ordered, non-cacheable, bufferable, shareable, |
|
||||
* | | | non-trustable |
|
||||
* | PMA | 01110 | Weakly-ordered, cacheable, bufferable, shareable, |
|
||||
* | | | non-trustable |
|
||||
* | IO | 10010 | Strongly-ordered, non-cacheable, non-bufferable, |
|
||||
* | | | shareable, non-trustable |
|
||||
* +------+-------+------------------------------------------------------------+
|
||||
*/
|
||||
#define PTE_THEAD_MA_SHIFT 59
|
||||
#define PTE_THEAD_MA_MASK (0x1ful << PTE_THEAD_MA_SHIFT)
|
||||
#define PTE_THEAD_MA_NC (0x6ul << PTE_THEAD_MA_SHIFT)
|
||||
#define PTE_THEAD_MA_NONE (0xeul << PTE_THEAD_MA_SHIFT)
|
||||
#define PTE_THEAD_MA_IO (0x12ul << PTE_THEAD_MA_SHIFT)
|
||||
|
||||
/* Bits 63 - 54 are reserved for future use. */
|
||||
#define PTE_HI_MASK 0xFFC0000000000000ULL
|
||||
|
||||
|
@ -123,6 +123,8 @@
|
||||
#define SBI_REMOTE_SFENCE_VMA_ASID 7
|
||||
#define SBI_SHUTDOWN 8
|
||||
|
||||
#ifndef LOCORE
|
||||
|
||||
#define SBI_CALL0(e, f) SBI_CALL5(e, f, 0, 0, 0, 0, 0)
|
||||
#define SBI_CALL1(e, f, p1) SBI_CALL5(e, f, p1, 0, 0, 0, 0)
|
||||
#define SBI_CALL2(e, f, p1, p2) SBI_CALL5(e, f, p1, p2, 0, 0, 0)
|
||||
@ -242,4 +244,5 @@ sbi_console_getchar(void)
|
||||
void sbi_print_version(void);
|
||||
void sbi_init(void);
|
||||
|
||||
#endif /* !LOCORE */
|
||||
#endif /* !_MACHINE_SBI_H_ */
|
||||
|
37
sys/riscv/include/thead.h
Normal file
37
sys/riscv/include/thead.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 The FreeBSD Foundation
|
||||
*
|
||||
* This software was developed by Mitchell Horne <mhorne@FreeBSD.org> under
|
||||
* sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _RISCV_THEAD_H_
|
||||
#define _RISCV_THEAD_H_
|
||||
|
||||
extern bool has_errata_thead_pbmt;
|
||||
|
||||
void thead_setup_cache(void);
|
||||
|
||||
#endif /* _RISCV_THEAD_H_ */
|
53
sys/riscv/riscv/cache.c
Normal file
53
sys/riscv/riscv/cache.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 The FreeBSD Foundation
|
||||
*
|
||||
* This software was developed by Mitchell Horne <mhorne@FreeBSD.org> under
|
||||
* sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
struct riscv_cache_ops __read_frequently cache_ops;
|
||||
|
||||
int64_t __read_frequently dcache_line_size; /* The minimum D cache line size */
|
||||
|
||||
static bool cache_initialized;
|
||||
|
||||
void
|
||||
riscv_cache_install_hooks(struct riscv_cache_ops *newops, u_int line_size)
|
||||
{
|
||||
if (cache_initialized)
|
||||
panic("cache hooks already installed!");
|
||||
|
||||
bcopy(newops, &cache_ops, sizeof(cache_ops));
|
||||
dcache_line_size = line_size;
|
||||
|
||||
cache_initialized = true;
|
||||
}
|
@ -52,6 +52,7 @@
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/elf.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/thead.h>
|
||||
|
||||
#ifdef FDT
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
@ -463,6 +464,38 @@ identify_cpu_ids(struct cpu_desc *desc)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_thead_quirks(u_int cpu, struct cpu_desc *desc)
|
||||
{
|
||||
if (cpu != 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* For now, it is assumed that T-HEAD CPUs have both marchid and mimpid
|
||||
* values of zero (although we leave this unchecked). It is true in
|
||||
* practice for the early generations of this hardware (C906, C910,
|
||||
* C920). In the future, the identity checks may need to become more
|
||||
* granular, but until then all known T-HEAD quirks are applied
|
||||
* indiscriminantly.
|
||||
*
|
||||
* Note: any changes in this function relating to has_errata_thead_pbmt
|
||||
* may need to be applied to get_pte_fixup_bits (in locore.S) as well.
|
||||
*/
|
||||
|
||||
has_errata_thead_pbmt = true;
|
||||
thead_setup_cache();
|
||||
}
|
||||
|
||||
static void
|
||||
handle_cpu_quirks(u_int cpu, struct cpu_desc *desc)
|
||||
{
|
||||
switch (mvendorid) {
|
||||
case MVENDORID_THEAD:
|
||||
handle_thead_quirks(cpu, desc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
identify_cpu(u_int cpu)
|
||||
{
|
||||
@ -472,6 +505,7 @@ identify_cpu(u_int cpu)
|
||||
identify_cpu_features(cpu, desc);
|
||||
|
||||
update_global_capabilities(cpu, desc);
|
||||
handle_cpu_quirks(cpu, desc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -42,9 +42,11 @@
|
||||
#include "assym.inc"
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/param.h>
|
||||
#include <machine/riscvreg.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/riscvreg.h>
|
||||
#include <machine/sbi.h>
|
||||
|
||||
.globl kernbase
|
||||
.set kernbase, KERNBASE
|
||||
@ -83,8 +85,12 @@ _alt_start:
|
||||
lla t0, boot_hart
|
||||
sw a0, 0(t0)
|
||||
|
||||
/* Load zero as modulep */
|
||||
mv a0, zero
|
||||
/*
|
||||
* Stash the DTB pointer in the callee-saved register s4, and zero s3
|
||||
* to indicate that we have no loader metadata.
|
||||
*/
|
||||
mv s4, a1
|
||||
mv s3, zero
|
||||
j pagetables
|
||||
|
||||
/*
|
||||
@ -104,10 +110,12 @@ _start:
|
||||
.option pop
|
||||
|
||||
/*
|
||||
* Zero a1 to indicate that we have no DTB pointer. It is already
|
||||
* included in the loader(8) metadata.
|
||||
* Stash modulep in the callee-saved register s3, and zero s4 to
|
||||
* indicate that we have no DTB pointer. It is already included in the
|
||||
* loader(8) metadata.
|
||||
*/
|
||||
mv a1, zero
|
||||
mv s3, a0
|
||||
mv s4, zero
|
||||
|
||||
/*
|
||||
* Set up page tables: Our goal is to enable virtual memory, doing the
|
||||
@ -128,19 +136,23 @@ _start:
|
||||
* here and will conditionally enable Sv48 (or higher) later.
|
||||
*
|
||||
* We arrive here with:
|
||||
* a0 - modulep or zero
|
||||
* a1 - zero or dtbp
|
||||
* s3 - modulep or zero
|
||||
* s4 - zero or dtbp
|
||||
*/
|
||||
pagetables:
|
||||
/* Get the kernel's load address (kernstart) in s9 */
|
||||
jal get_physmem
|
||||
|
||||
/* Get PTE attribute bits in s8 */
|
||||
jal get_pte_fixup_bits
|
||||
|
||||
/* Construct 1GB Identity Map (1:1 PA->VA) */
|
||||
lla s1, bootstrap_pt_l1
|
||||
|
||||
srli s2, s9, L1_SHIFT /* kernstart >> L1_SHIFT */
|
||||
andi a5, s2, Ln_ADDR_MASK /* & Ln_ADDR_MASK */
|
||||
li t4, (PTE_KERN)
|
||||
or t4, t4, s8 /* t4 |= pte bits */
|
||||
slli s2, s2, PTE_PPN2_S /* (s2 << PTE_PPN2_S) */
|
||||
or t6, t4, s2
|
||||
|
||||
@ -176,6 +188,7 @@ pagetables:
|
||||
li t2, Ln_ENTRIES /* Build 512 entries */
|
||||
add t3, t4, t2
|
||||
li t0, (PTE_KERN | PTE_X)
|
||||
or t0, t0, s8 /* t0 |= pte bits */
|
||||
1:
|
||||
slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */
|
||||
or t5, t0, t2
|
||||
@ -244,8 +257,8 @@ va:
|
||||
|
||||
la t0, initstack
|
||||
sd t0, RISCV_BOOTPARAMS_KERN_STACK(sp)
|
||||
sd a1, RISCV_BOOTPARAMS_DTBP_PHYS(sp)
|
||||
sd a0, RISCV_BOOTPARAMS_MODULEP(sp)
|
||||
sd s4, RISCV_BOOTPARAMS_DTBP_PHYS(sp)
|
||||
sd s3, RISCV_BOOTPARAMS_MODULEP(sp)
|
||||
|
||||
mv a0, sp
|
||||
call _C_LABEL(initriscv) /* Off we go */
|
||||
@ -267,6 +280,28 @@ get_physmem:
|
||||
sub s9, t2, t1 /* s9 = physmem base */
|
||||
ret
|
||||
|
||||
/*
|
||||
* T-HEAD CPUs implement an alternate scheme for PTE attributes that is
|
||||
* incompatible with the RISC-V PTE specification (see the definitions in
|
||||
* pte.h). Worse, it defines a non-zero value for "main" memory, and this must
|
||||
* be set in order to proceed with our new page tables.
|
||||
*
|
||||
* Therefore, we are forced to check the CPU identity here, which is both
|
||||
* inconvenient and fragile.
|
||||
*
|
||||
* Return the required attribute bits in s8. For sane implementations this is
|
||||
* zero.
|
||||
*/
|
||||
get_pte_fixup_bits:
|
||||
mv s8, zero
|
||||
SBI_CALL(SBI_EXT_ID_BASE, SBI_BASE_GET_MVENDORID)
|
||||
li t0, MVENDORID_THEAD
|
||||
xor t0, t0, a1
|
||||
bnez t0, 1f /* branch if a1 != t0 */
|
||||
li s8, PTE_THEAD_MA_NONE
|
||||
1:
|
||||
ret
|
||||
|
||||
.align 4
|
||||
initstack:
|
||||
.space (PAGE_SIZE * KSTACK_PAGES)
|
||||
|
@ -113,10 +113,6 @@ int cold = 1;
|
||||
|
||||
struct kva_md_info kmi;
|
||||
|
||||
int64_t dcache_line_size; /* The minimum D cache line size */
|
||||
int64_t icache_line_size; /* The minimum I cache line size */
|
||||
int64_t idcache_line_size; /* The minimum cache line size */
|
||||
|
||||
#define BOOT_HART_INVALID 0xffffffff
|
||||
uint32_t boot_hart = BOOT_HART_INVALID; /* The hart we booted on. */
|
||||
|
||||
@ -329,17 +325,6 @@ try_load_dtb(caddr_t kmdp)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cache_setup(void)
|
||||
{
|
||||
|
||||
/* TODO */
|
||||
|
||||
dcache_line_size = 0;
|
||||
icache_line_size = 0;
|
||||
idcache_line_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fake up a boot descriptor table.
|
||||
*/
|
||||
@ -550,8 +535,6 @@ initriscv(struct riscv_bootparams *rvbp)
|
||||
/* Do basic tuning, hz etc */
|
||||
init_param1();
|
||||
|
||||
cache_setup();
|
||||
|
||||
#ifdef FDT
|
||||
/*
|
||||
* XXX: Unconditionally exclude the lowest 2MB of physical memory, as
|
||||
|
@ -156,6 +156,7 @@
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/sbi.h>
|
||||
#include <machine/thead.h>
|
||||
|
||||
/*
|
||||
* Boundary values for the page table page index space:
|
||||
@ -867,6 +868,11 @@ pmap_bootstrap(vm_paddr_t kernstart, vm_size_t kernlen)
|
||||
memattr_bits[VM_MEMATTR_UNCACHEABLE] = PTE_MA_NC;
|
||||
memattr_bits[VM_MEMATTR_DEVICE] = PTE_MA_IO;
|
||||
memattr_mask = PTE_MA_MASK;
|
||||
} else if (has_errata_thead_pbmt) {
|
||||
memattr_bits[VM_MEMATTR_PMA] = PTE_THEAD_MA_NONE;
|
||||
memattr_bits[VM_MEMATTR_UNCACHEABLE] = PTE_THEAD_MA_NC;
|
||||
memattr_bits[VM_MEMATTR_DEVICE] = PTE_THEAD_MA_IO;
|
||||
memattr_mask = PTE_THEAD_MA_MASK;
|
||||
}
|
||||
|
||||
/* Create a new set of pagetables to run the kernel in. */
|
||||
@ -5013,7 +5019,7 @@ pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
|
||||
if (anychanged) {
|
||||
pmap_invalidate_range(kernel_pmap, base, tmpva);
|
||||
if (mode == VM_MEMATTR_UNCACHEABLE)
|
||||
cpu_dcache_wbinv_range((void *)base, size);
|
||||
cpu_dcache_wbinv_range(base, size);
|
||||
}
|
||||
|
||||
return (error);
|
||||
|
101
sys/riscv/thead/thead.c
Normal file
101
sys/riscv/thead/thead.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 The FreeBSD Foundation
|
||||
*
|
||||
* This software was developed by Mitchell Horne <mhorne@FreeBSD.org> under
|
||||
* sponsorship from the FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/thead.h>
|
||||
|
||||
bool has_errata_thead_pbmt = false;
|
||||
|
||||
/* ----------------- dcache ops --------------------- */
|
||||
|
||||
|
||||
/* th.dcache.civa: clean & invalidate at VA stored in t0. */
|
||||
#define THEAD_DCACHE_CIVA ".long 0x0272800b\n"
|
||||
|
||||
/* th.dcache.iva: invalidate at VA stored in t0. */
|
||||
#define THEAD_DCACHE_IVA ".long 0x0262800b\n"
|
||||
|
||||
/* th.dcache.cva: clean at VA stored in t0. */
|
||||
#define THEAD_DCACHE_CVA ".long 0x0252800b\n"
|
||||
|
||||
/* th.sync.s: two-way instruction barrier */
|
||||
#define THEAD_SYNC_S ".long 0x0190000b\n"
|
||||
|
||||
/* MHTODO: we could parse this information from the device tree. */
|
||||
#define THEAD_DCACHE_SIZE 64
|
||||
|
||||
static void
|
||||
thead_cpu_dcache_wbinv_range(vm_offset_t va, vm_size_t len)
|
||||
{
|
||||
register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
|
||||
|
||||
for (; t0 < va + len; t0 += dcache_line_size) {
|
||||
__asm __volatile(THEAD_DCACHE_CIVA
|
||||
:: "r" (t0) : "memory");
|
||||
}
|
||||
__asm __volatile(THEAD_SYNC_S ::: "memory");
|
||||
}
|
||||
|
||||
static void
|
||||
thead_cpu_dcache_inv_range(vm_offset_t va, vm_size_t len)
|
||||
{
|
||||
register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
|
||||
|
||||
for (; t0 < va + len; t0 += dcache_line_size) {
|
||||
__asm __volatile(THEAD_DCACHE_IVA
|
||||
:: "r" (t0) : "memory");
|
||||
}
|
||||
__asm __volatile(THEAD_SYNC_S ::: "memory");
|
||||
}
|
||||
|
||||
static void
|
||||
thead_cpu_dcache_wb_range(vm_offset_t va, vm_size_t len)
|
||||
{
|
||||
register vm_offset_t t0 __asm("t0") = rounddown(va, dcache_line_size);
|
||||
|
||||
for (; t0 < va + len; t0 += dcache_line_size) {
|
||||
__asm __volatile(THEAD_DCACHE_CVA
|
||||
:: "r" (t0) : "memory");
|
||||
}
|
||||
__asm __volatile(THEAD_SYNC_S ::: "memory");
|
||||
}
|
||||
|
||||
void
|
||||
thead_setup_cache(void)
|
||||
{
|
||||
struct riscv_cache_ops thead_ops;
|
||||
|
||||
thead_ops.dcache_wbinv_range = thead_cpu_dcache_wbinv_range;
|
||||
thead_ops.dcache_inv_range = thead_cpu_dcache_inv_range;
|
||||
thead_ops.dcache_wb_range = thead_cpu_dcache_wb_range;
|
||||
|
||||
riscv_cache_install_hooks(&thead_ops, THEAD_DCACHE_SIZE);
|
||||
}
|
@ -73,7 +73,7 @@
|
||||
* cannot include sys/param.h and should only be updated here.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1500027
|
||||
#define __FreeBSD_version 1500028
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
@ -494,6 +494,7 @@ enum {
|
||||
TDA_RACCT,
|
||||
TDA_MOD1, /* For third party use, before signals are */
|
||||
TAD_MOD2, /* processed .. */
|
||||
TDA_PSELECT, /* For discarding temporary signal mask */
|
||||
TDA_SIG,
|
||||
TDA_KTRACE,
|
||||
TDA_SUSPEND,
|
||||
@ -567,6 +568,7 @@ enum {
|
||||
#define TDP2_SBPAGES 0x00000001 /* Owns sbusy on some pages */
|
||||
#define TDP2_COMPAT32RB 0x00000002 /* compat32 ABI for robust lists */
|
||||
#define TDP2_ACCT 0x00000004 /* Doing accounting */
|
||||
#define TDP2_SAN_QUIET 0x00000008 /* Disable warnings from K(A|M)SAN */
|
||||
|
||||
/*
|
||||
* Reasons that the current thread can not be run yet.
|
||||
|
@ -277,7 +277,7 @@ amdiommu_create_dev_tbl(struct amdiommu_unit *sc)
|
||||
pmap_qenter(seg_vaddr, &m, 1);
|
||||
}
|
||||
reg = i == 0 ? AMDIOMMU_DEVTAB_BASE : AMDIOMMU_DEVTAB_S1_BASE +
|
||||
i - 1;
|
||||
((i - 1) << 3);
|
||||
amdiommu_write8(sc, reg, rval);
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,75 @@ v6_cleanup()
|
||||
pft_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "v6_route_to" "cleanup"
|
||||
v6_route_to_head()
|
||||
{
|
||||
atf_set descr 'Test IPv6 reassembly combined with route-to'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
v6_route_to_body()
|
||||
{
|
||||
pft_init
|
||||
}
|
||||
|
||||
v6_route_to_cleanup()
|
||||
{
|
||||
pft_cleanup
|
||||
|
||||
epair_send=$(vnet_mkepair)
|
||||
epair_link=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail alcatraz ${epair_send}b ${epair_link}a
|
||||
vnet_mkjail singsing ${epair_link}b
|
||||
|
||||
ifconfig ${epair_send}a inet6 2001:db8:42::1/64 no_dad up
|
||||
|
||||
jexec alcatraz ifconfig ${epair_send}b inet6 2001:db8:42::2/64 no_dad up
|
||||
jexec alcatraz ifconfig ${epair_link}a inet6 2001:db8:43::2/64 no_dad up
|
||||
jexec alcatraz sysctl net.inet6.ip6.forwarding=1
|
||||
|
||||
jexec singsing ifconfig ${epair_link}b inet6 2001:db8:43::3/64 no_dad up
|
||||
jexec singsing route add -6 2001:db8:42::/64 2001:db8:43::2
|
||||
route add -6 2001:db8:43::/64 2001:db8:42::2
|
||||
|
||||
jexec alcatraz ifconfig ${epair_send}b inet6 -ifdisabled
|
||||
jexec alcatraz ifconfig ${epair_link}a inet6 -ifdisabled
|
||||
jexec singsing ifconfig ${epair_link}b inet6 -ifdisabled
|
||||
ifconfig ${epair_send}a inet6 -ifdisabled
|
||||
|
||||
jexec alcatraz pfctl -e
|
||||
pft_set_rules alcatraz \
|
||||
"set reassemble yes" \
|
||||
"pass" \
|
||||
"pass in route-to (${epair_link}a 2001:db8:43::3) inet6 proto icmp6 from any to 2001:db8:43::3 keep state"
|
||||
|
||||
# Forwarding test
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 -s 4500 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore\
|
||||
ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3
|
||||
|
||||
# Now test this without fragmentation
|
||||
pft_set_rules alcatraz \
|
||||
"set reassemble no" \
|
||||
"pass" \
|
||||
"pass in route-to (${epair_link}a 2001:db8:43::3) inet6 proto icmp6 from any to 2001:db8:43::3 keep state"
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore \
|
||||
ping -6 -c 1 -s 4500 2001:db8:43::3
|
||||
|
||||
atf_check -s exit:0 -o ignore\
|
||||
ping -6 -c 1 -b 70000 -s 65000 2001:db8:43::3
|
||||
}
|
||||
|
||||
atf_test_case "mtu_diff" "cleanup"
|
||||
mtu_diff_head()
|
||||
{
|
||||
@ -544,6 +613,7 @@ atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "too_many_fragments"
|
||||
atf_add_test_case "v6"
|
||||
atf_add_test_case "v6_route_to"
|
||||
atf_add_test_case "mtu_diff"
|
||||
atf_add_test_case "overreplace"
|
||||
atf_add_test_case "overindex"
|
||||
|
@ -578,7 +578,7 @@ netname4(in_addr_t in, in_addr_t mask)
|
||||
struct netent *np = 0;
|
||||
in_addr_t i;
|
||||
|
||||
if (in == INADDR_ANY && mask == 0) {
|
||||
if (!numeric_addr && in == INADDR_ANY && mask == 0) {
|
||||
strlcpy(line, "default", sizeof(line));
|
||||
return (line);
|
||||
}
|
||||
@ -673,7 +673,8 @@ netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask)
|
||||
else
|
||||
masklen = 128;
|
||||
|
||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||
if (!numeric_addr && masklen == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||
return("default");
|
||||
|
||||
getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, nline, sizeof(nline),
|
||||
|
@ -160,7 +160,7 @@ setup_and_wait(struct trussinfo *info, char *command[])
|
||||
|
||||
/* Only in the parent here */
|
||||
if (waitpid(pid, NULL, 0) < 0)
|
||||
err(1, "unexpect stop in waitpid");
|
||||
err(1, "unexpected stop in waitpid");
|
||||
|
||||
new_proc(info, pid, 0);
|
||||
}
|
||||
@ -179,10 +179,10 @@ start_tracing(struct trussinfo *info, pid_t pid)
|
||||
usleep(200);
|
||||
} while (ret && retry-- > 0);
|
||||
if (ret)
|
||||
err(1, "can not attach to target process");
|
||||
err(1, "Cannot attach to target process");
|
||||
|
||||
if (waitpid(pid, NULL, 0) < 0)
|
||||
err(1, "Unexpect stop in waitpid");
|
||||
err(1, "Unexpected stop in waitpid");
|
||||
|
||||
new_proc(info, pid, 0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user